diff options
733 files changed, 23954 insertions, 24437 deletions
diff --git a/.clang-format b/.clang-format index 3a2c39a174..237fd9ce30 100644 --- a/.clang-format +++ b/.clang-format @@ -116,6 +116,7 @@ Standard: Cpp03 --- ### ObjC specific config ### Language: ObjC +Standard: Cpp03 ObjCBlockIndentWidth: 4 # ObjCSpaceAfterProperty: false # ObjCSpaceBeforeProtocolList: true diff --git a/.travis.yml b/.travis.yml index c3302cf806..65565db6f1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,14 +1,14 @@ language: cpp # OS config, depends on actual 'os' in build matrix -dist: trusty +dist: xenial sudo: false env: global: - SCONS_CACHE=$HOME/.scons_cache - SCONS_CACHE_LIMIT=1024 - - OPTIONS="debug_symbols=no verbose=yes progress=no gdnative_wrapper=yes" + - OPTIONS="debug_symbols=no verbose=yes progress=no" - secure: "uch9QszCgsl1qVbuzY41P7S2hWL2IiNFV4SbAYRCdi0oJ9MIu+pVyrQdpf3+jG4rH6j4Rffl+sN17Zz4dIDDioFL1JwqyCqyCyswR8uACC0Rr8gr4Mi3+HIRbv+2s2P4cIQq41JM8FJe84k9jLEMGCGh69w+ibCWoWs74CokYVA=" cache: @@ -23,20 +23,20 @@ matrix: addons: apt: sources: - - llvm-toolchain-trusty-6.0 - - ubuntu-toolchain-r-test + - llvm-toolchain-xenial-6.0 packages: - clang-format-6.0 - - libstdc++6 # >= 4.9 needed for clang-format-6.0 - - env: PLATFORM=x11 TOOLS=yes TARGET=debug CACHE_NAME=${PLATFORM}-tools-mono-gcc EXTRA_ARGS="module_mono_enabled=yes mono_glue=no werror=yes" + - env: PLATFORM=x11 TOOLS=yes TARGET=debug CACHE_NAME=${PLATFORM}-tools-mono-gcc-8 MATRIX_EVAL="CC=gcc-8 && CXX=g++-8" EXTRA_ARGS="module_mono_enabled=yes mono_glue=no werror=yes" os: linux - compiler: gcc + compiler: gcc-8 addons: apt: sources: - mono + - ubuntu-toolchain-r-test packages: + - &gcc8_deps [gcc-8, g++-8] - &linux_deps [libasound2-dev, libfreetype6-dev, libgl1-mesa-dev, libglu1-mesa-dev, libx11-dev, libxcursor-dev, libxi-dev, libxinerama-dev, libxrandr-dev] - &linux_mono_deps [mono-devel, msbuild, nuget] @@ -69,7 +69,18 @@ matrix: os: osx compiler: clang - - env: PLATFORM=server TOOLS=yes TARGET=release_debug CACHE_NAME=${PLATFORM}-tools-gcc + - env: PLATFORM=server TOOLS=yes TARGET=release_debug CACHE_NAME=${PLATFORM}-tools-gcc-8 MATRIX_EVAL="CC=gcc-8 && CXX=g++-8" EXTRA_ARGS="werror=yes" + os: linux + compiler: gcc-8 + addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - *gcc8_deps + - *linux_deps + + - env: PLATFORM=x11 TOOLS=no TARGET=release_debug CACHE_NAME=${PLATFORM}-gcc-5 os: linux compiler: gcc addons: @@ -78,16 +89,17 @@ matrix: - *linux_deps before_install: + - eval "${MATRIX_EVAL}" - if [ "$STATIC_CHECKS" = "yes" ]; then unset SCONS_CACHE; fi install: + - pip install --user scons; - if [ "$TRAVIS_OS_NAME" = "linux" ] && [ "$PLATFORM" = "android" ]; then misc/travis/android-tools-linux.sh; fi - if [ "$TRAVIS_OS_NAME" = "osx" ]; then - pip install --user scons; export PATH=${PATH}:/Users/travis/Library/Python/2.7/bin; fi - if [ "$TRAVIS_OS_NAME" = "osx" ] && [ "$PLATFORM" = "android" ]; then @@ -104,5 +116,5 @@ script: - if [ "$STATIC_CHECKS" = "yes" ]; then sh ./misc/travis/clang-format.sh; else - scons -j2 CC=$CC CXX=$CXX platform=$PLATFORM tools=$TOOLS target=$TARGET $EXTRA_ARGS $OPTIONS; + scons -j2 CC=$CC CXX=$CXX platform=$PLATFORM tools=$TOOLS target=$TARGET $OPTIONS $EXTRA_ARGS; fi diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a0310f904..b111eca07d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,251 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/). +## [Unreleased] + +### Added + +- OpenGL ES 2.0 renderer. +- [Visual shader editor.](https://godotengine.org/article/visual-shader-editor-back) + - New PBR output nodes. + - Conversion between Vector3 and scalar types is now automatic. + - Ability to create custom nodes via scripting. + - Ports can now be previewed. +- [3D soft body physics.](https://godotengine.org/article/soft-body) +- [3D ragdoll system.](https://godotengine.org/article/godot-ragdoll-system) +- [Constructive solid geometry in 3D.](https://godotengine.org/article/godot-gets-csg-support) +- [2D meshes and skeletal deformation.](https://godotengine.org/article/godot-gets-2d-skeletal-deform) +- [Various improvements to KinematicBody2D.](https://godotengine.org/article/godot-31-will-get-many-improvements-kinematicbody) + - Support for snapping the body to the floor. + - Support for RayCast shapes in kinematic bodies. + - Support for synchronizing kinematic movement to physics, avoiding an one-frame delay. +- WebSockets support using [libwebsockets](https://libwebsockets.org/). +- [Revamped inspector.](https://godotengine.org/article/godot-gets-new-inspector) + - Improved visualization and editing of numeric properties. + - Vector and matrix types can now be edited directly (no pop-ups). + - Subresources can now be edited directly within the same inspector. + - Layer names can now be displayed in the inspector. + - Proper editing of arrays and dictionaries. + - Ability to reset any property to its default value. +- [Improved animation editor.](https://godotengine.org/article/godot-gets-brand-new-animation-editor-cinematic-support) + - Simpler, less cluttered layout. + - New Bezier, Audio and Animation tracks. + - Several key types can be previewed directly in the track editor. + - Tracks can now be grouped and filtered on a per-node basis. + - Copying and pasting tracks between animations is now possible. + - New Capture mode to blend from a node's current value to the first key in a track. +- [Improved animation tree and new state machine.](https://godotengine.org/article/godot-gets-new-animation-tree-state-machine) + - More visual feedback in the blend tree editor. + - 1D and 2D blend spaces are now supported. + - Ability to write custom blending logic. + - Support for root motion. +- [New FileSystem dock.](https://godotengine.org/article/godot-gets-new-filesystem-dock-3-1) + - Unified view of folders and files in the same panel. + - Files can now be marked as favorites, not only folders. + - Files now have icons representing their type, or thumbnail previews when relevant. + - New search field to filter entries in the tree. +- [OpenSimplexNoise and NoiseTexture resources.](https://godotengine.org/article/simplex-noise-lands-godot-31) +- [Optional static typing in GDScript.](https://godotengine.org/article/optional-typing-gdscript) + - Does not currently improve performance, but helps write more robust code. +- Warning system in GDScript. + - Reports potential code issues such as: + - unused variables, + - standalone expressions, + - discarded return values from functions, + - unreachable code after a `return` statement, + - … + - Warnings can be disabled in the Project Settings or by writing special comments. +- [GDScript keyword `class_name` to register scripts as classes.](http://docs.godotengine.org/en/latest/getting_started/step_by_step/scripting_continued.html#register-scripts-as-classes) +- Simple expression language independent from GDScript, used by inspector boxes that accept numeric values. + - Can also be used in projects. +- C# projects can now be exported for Windows, Linux, and macOS targets. +- The `server` platform is back as it was in Godot 2.1. + - It is now again possible to run a headless Godot instance on Linux. +- Support for BPTC texture compression on desktop platforms. +- New properties for SpatialMaterial. + - Dithering-based distance fade, for fading materials without making them transparent. + - Disable ambient light on a per-material basis. +- Option to link Mono statically on Windows. +- Unified class and reference search in the editor. +- Revamped TileSet editor with support for undo/redo operations. +- Various quality-of-life improvements to the Polygon2D and TextureRegion editors. +- RandomNumberGenerator class that allows for multiple instances at once. +- Array methods `min()` and `max()` to return the smallest and largest value respectively. +- Dictionary method `get(key[, default])` where `default` is returned if the key does not exist. +- Node method `print_tree_pretty()` to print a graphical view of the scene tree. +- String methods `trim_prefix()`, `trim_suffix()`, `lstrip()`, `rstrip()`. +- OS methods: + - `get_system_time_msecs()`: Return the system time with milliseconds. + - `get_audio_driver_name()` and `get_audio_driver_count()` to query audio driver information. + - `get_video_driver_count()` and `get_video_driver_name()` to query renderer information. + - `center_window()`: Center the window on the screen. + - `move_window_to_foreground()`: Move the window to the foreground. +- StreamPeerTCP method `set_no_delay()` to enable the `TCP_NODELAY` option. +- EditorPlugin method `remove_control_from_container()`. +- Ability to set Godot windows as "always on top". +- Ability to create windows with per-pixel transparency. +- New GLSL built-in functions in the shader language: + - `radians()` + - `degrees()` + - `asinh()` + - `acosh()` + - `atanh()` + - `exp2()` + - `log2()` + - `roundEven()` +- New command-line options: + - `--build-solutions`: Build C# solutions without starting the editor. + - `--print-fps`: Display frames per second to standard output. + - `--quit`: Quit the engine after the first main loop iteration. +- Debugger button to copy error messages. +- Support for `.escn` scenes has been added for use with the new Blender exporter. +- It is now possible to scale an OBJ mesh when importing. +- `popup_closed` signal for `ColorPickerButton`. +- Methods that are deprecated can now print warnings. +- Input actions can now provide an analog value. +- Input actions can now be mapped to either a specific device or all devices. +- DNS resolution for high-level networking. +- Servers can now kick/disconnect peers in high-level networking. +- Servers can now access IP and port information of peers in high-level networking. +- High-level multiplayer API decoupled from SceneTree (see `SceneTree.multiplayer_api`/`SceneTree.custom_multiplayer_api`), can now be extended. +- `Input.set_default_cursor_shape()` to change the default shape in the viewport. +- Custom cursors can now be as large as 256×256 (needed to be exactly 32×32 before). +- Support for radio-looking items with icon in `PopupMenu`s. +- Drag and drop to rearrange Editor docks. +- TileSet's `TileMode` is now exposed to GDScript. +- `OS.get_ticks_usec()` is now exposed to GDScript. +- Normals can now be flipped when generated via `SurfaceTool`. +- TextureProgress bars can now be bilinear (extending in both directions). +- The character used for masking secrets in LineEdit can now be changed. +- Improved DynamicFont: + - DynamicFonts can now use high-quality outlines generated by FreeType. + - DynamicFonts can now have their anti-aliasing disabled. + - DynamicFonts can now have their hinting tweaked ("Normal", "Light" or "None"). + - Colored glyphs such as emoji are now supported. +- Universal translation of touch input to mouse input. +- AudioStreamPlayer, AudioStreamPlayer2D, and AudioStreamPlayer3D now have a pitch scale property. +- Support for MIDI input. +- `GROW_DIRECTION_BOTH` for Controls. +- Selected tiles can be moved in the tile map editor. +- The editor can now be configured to display the project window on the previous or next monitor (relative to the editor). + - If either end is reached, then the project will start on the last or first monitor (respectively). +- Signal in VideoPlayer to notify when the video finished playing. +- `Image.bumpmap_to_normalmap()` to convert bump maps to normal maps. +- `File.get_path()` and `File.get_path_absolute()`. +- Unselected tabs in the editor now have a subtle background for easier identification. +- The depth fog's end distance is now configurable independently of the far plane distance. +- The alpha component of the fog color can now be used to control fog density. +- The 3D editor's information panel now displays the camera's coordinates. +- New options to hide the origin and viewport in the 2D editor. +- Improved 3D editor grid: + - The grid size and number of subdivisions can now be configured. + - Its primary and secondary colors can now also be changed. +- <kbd>Ctrl</kbd> now toggles snapping in the 3D viewport. +- Find & replace in files (<kbd>Ctrl + Shift + F</kbd> by default). +- Batch node renaming tool (<kbd>Ctrl + F2</kbd> by default). +- More editor scaling options to support HiDPI displays. +- Type icons can now be enabled in the editor again. +- Buttons in the editor to open common directories in the OS file manager: + - project data directory, + - user data directory, + - user settings directory. +- Projects can now be sorted by name or modification date in the project manager. +- Projects can now be imported from ZIP archives in the project manager. +- Improved autocompletion. + - Keywords are now present in autocompletion results. +- `editor` and `standalone` feature tags to check whether the project is running from an editor or non-editor binary. +- `android_add_asset_dir("...")` method to Android module Gradle build configuration. +- **iOS:** Support for exporting to the iPhone X. +- **iOS:** Readded support for in-app purchases. + +### Changed + +- [Built-in vector types now use copy-on-write mode as originally intended](https://godotengine.org/article/why-we-broke-your-pr), resulting in increased engine performance. +- The [mbedtls](https://tls.mbed.org/) library is now used instead of OpenSSL. +- SSL certificates are now bundled in exported projects unless a custom bundle is specified. +- Improved buffer writing performance on Windows and Linux. +- Removed many debugging prints in the console. +- Export templates now display an error dialog if no project was found when starting. +- DynamicFont oversampling is now enabled by default. +- Nodes' internal logic now consistently use internal physics processing. +- Allow attaching and clearing scripts on multiple nodes at once. +- Default values are no longer saved in scene and resource files. +- The selection rectangle of 2D nodes is now hidden when not pertinent (no more rectangle for collision shapes). +- SSE2 is now enabled in libsquish, resulting in improved S3TC encoding performance. +- Tangent and binormal coordinates are now more consistent across mesh types (primitive/imported), resulting in more predictable normal map and depth map appearance. +- Better defaults for 3D scenes. + - The default procedural sky now has a more neutral blue tone. + - The default SpatialMaterial now has a roughness value of 1 and metallic value of 0. + - The fallback material now uses the same values as the default SpatialMaterial. +- Text editor themes are now sorted alphabetically in the selection dropdown. +- The 3D manipulator gizmo now has a smoother, more detailed appearance. +- The 3D viewport menu button now has a background to make it easier to read. +- Controls inside containers are no longer movable or resizable but can still be selected. +- The `is` GDScript keyword can now be used to compare a value against built-in types. +- Named enums in GDScript no longer create script constants. + - This means `enum Name { VALUE }` must now be accessed with `Name.VALUE` instead of `VALUE`. +- Shadowing variables from parent scopes is no longer allowed in GDScript. +- Function parameters' default values can no longer depend on other parameters in GDScript. +- Indentation guides are now displayed in a more subtle way in the script editor. + - Indentation guides are now displayed when indenting using spaces. +- Multi-line strings are now highlighted as strings rather than as comments in the script editor. + - This is because GDScript does not officially support multiline comments. +- Increased the script editor's line spacing (4 pixels → 6 pixels). +- Increased the caret width in the script editor (1 pixel → 2 pixels). +- The project manager window is now resized to match the editor scale. +- The asset library now makes use of threading, making loading more responsive. +- Line spacing in the script editor, underlines and caret widths are now resized to match the editor scale. +- Replaced editor icons for checkboxes and radio buttons with simpler designs. +- Tweaked the editor's success, error, and warning text colors for better readability and consistency. +- **Android:** Custom permissions are now stored in an array and their amount is no longer limited to 20. + - Custom permissions will have to be redefined in projects imported from older versions. +- **Android:** Provide error details when an in-app purchase fails. +- **Linux:** `OS.alert()` now uses Zenity or KDialog if available instead of xmessage. +- **Mono:** Display stack traces for inner exceptions. +- **Mono:** Bundle `mscorlib.dll` with Godot to improve portability. + +### Removed + +- **macOS:** Support for 32-bit and fat binaries. + +### Fixed + +- [`move_and_slide()` now behaves differently at low velocities](https://github.com/godotengine/godot/issues/21683), which makes it function as originally intended. +- AnimatedSprite2D's `animation_finished` signal is now triggered at the end of the animation, instead of as soon as the last frame displays. +- Audio buses can now be removed in the editor while they are used by AudioStreamPlayer2D/3D nodes. +- Do not show the project manager unless no project was found at all. +- The animation editor time offset indicator no longer "walks" when resizing the editor. +- Allow creation of a built-in GDScript file even if the filename suggested already exists. +- Show tooltips in the editor when physics object picking is disabled. +- Fix a serialization bug that could cause TSCN files to grow very large. +- Gizmos are now properly hidden on scene load if the object they control is hidden. +- Camera gizmos in the 3D viewport no longer look twice as wide as they actually are. +- Copy/pasting from the editor on X11 will now work more reliably. +- `libgcc_s` and `libstdc++` are now linked statically for better Linux binary portability. +- The FPS cap set by `force_fps` in the Project Settings is no longer applied to the editor. + - Low FPS caps no longer cause the editor to feel sluggish. +- hiDPI is now detected and used if needed in the project manager. +- The Visual Studio Code external editor option now recognizes more binary names such as `code-oss`, making detection more reliable. +- The `-ffast-math` flag is no longer used when compiling Godot, resulting in increased floating-point determinism. +- Fix spelling of `apply_torque_impulse()` and deprecate the misspelled method. +- Remove spurious errors when using a PanoramaSky without textures. +- The lightmap baker will now use all available cores on Windows. +- Bullet physics now correctly calculates effective gravity on KinematicBodies. +- Setting the color `v` member now correctly sets the `s` member. +- RichTextLabels now correctly determine the baseline for all fonts. +- SpinBoxes now correctly calculate their initial size. +- OGG streams now correctly signal the end of playback. +- Android exporter no longer writes unnecessary permissions to the exported APK. +- Debugger "focus stealing" now works more reliably. +- Subresources are now always saved when saving a scene. +- Many fixes related to importers (glTF, Collada, audio), physics (Bullet), Mono/C#, GDNative, Android/iOS. +- **Mono:** Many fixes and improvements to C# support (including a `[Signal]` attribute). +- **WebAssembly:** Supply proper CORS headers. + +### Security + +- Fixed a security issue relating to deserializing Variants. + ## [3.0] - 2018-01-29 ### Added @@ -137,4 +382,5 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/). - HTML5 export using asm.js. - Only WebAssembly is supported now, since all browsers supporting WebGL 2.0 also support WebAssembly. +[Unreleased]: https://github.com/godotengine/godot/compare/3.0-stable...HEAD [3.0]: https://github.com/godotengine/godot/compare/2.1-stable...3.0-stable diff --git a/CODEOWNERS b/CODEOWNERS index 3a973a100a..e25eefb1dd 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -18,7 +18,6 @@ doc_classes/* @godotengine/documentation /drivers/coreaudio/ @marcelofg55 /drivers/coremidi/ @marcelofg55 /drivers/pulseaudio/ @marcelofg55 -/drivers/rtaudio/ @marcelofg55 /drivers/wasapi/ @marcelofg55 /drivers/winmidi/ @marcelofg55 /drivers/xaudio2/ @marcelofg55 diff --git a/COPYRIGHT.txt b/COPYRIGHT.txt index 17141df66f..be03fb44c5 100644 --- a/COPYRIGHT.txt +++ b/COPYRIGHT.txt @@ -362,11 +362,6 @@ Comment: Recast Copyright: 2009, Mikko Mononen License: Zlib -Files: ./thirdparty/rtaudio/ -Comment: RtAudio -Copyright: 2001-2016, Gary P. Scavone -License: Expat - Files: ./thirdparty/squish/ Comment: libSquish Copyright: 2006, Simon Brown diff --git a/SConstruct b/SConstruct index 57fa305a15..3734268cae 100644 --- a/SConstruct +++ b/SConstruct @@ -2,11 +2,13 @@ EnsureSConsVersion(0, 98, 1) -import string -import os -import os.path +# System import glob +import os +import string import sys + +# Local import methods import gles_builders from platform_methods import run_in_subprocess @@ -27,7 +29,7 @@ for x in sorted(glob.glob("platform/*")): continue tmppath = "./" + x - sys.path.append(tmppath) + sys.path.insert(0, tmppath) import detect if (os.path.exists(x + "/export/export.cpp")): @@ -86,13 +88,6 @@ env_base.split_modules = False env_base.module_version_string = "" env_base.msvc = False -# To decide whether to rebuild a file, use the MD5 sum only if the timestamp has changed. -# http://scons.org/doc/production/HTML/scons-user/ch06.html#idm139837621851792 -env_base.Decider('MD5-timestamp') -# Use cached implicit dependencies by default. Can be overridden by specifying `--implicit-deps-changed` in the command line. -# http://scons.org/doc/production/HTML/scons-user/ch06s04.html -env_base.SetOption('implicit_cache', 1) - env_base.__class__.android_add_maven_repository = methods.android_add_maven_repository env_base.__class__.android_add_flat_dir = methods.android_add_flat_dir env_base.__class__.android_add_dependency = methods.android_add_dependency @@ -130,7 +125,6 @@ customs = ['custom.py'] profile = ARGUMENTS.get("profile", False) if profile: - import os.path if os.path.isfile(profile): customs.append(profile) elif os.path.isfile(profile + ".py"): @@ -210,7 +204,7 @@ for k in platform_opts.keys(): for x in module_list: module_enabled = True tmppath = "./modules/" + x - sys.path.append(tmppath) + sys.path.insert(0, tmppath) import config enabled_attr = getattr(config, "is_enabled", None) if (callable(enabled_attr) and not config.is_enabled()): @@ -233,6 +227,16 @@ env_base.platform_apis = platform_apis if (env_base['target'] == 'debug'): env_base.Append(CPPDEFINES=['DEBUG_MEMORY_ALLOC','DISABLE_FORCED_INLINE']) + # The two options below speed up incremental builds, but reduce the certainty that all files + # will properly be rebuilt. As such, we only enable them for debug (dev) builds, not release. + + # To decide whether to rebuild a file, use the MD5 sum only if the timestamp has changed. + # http://scons.org/doc/production/HTML/scons-user/ch06.html#idm139837621851792 + env_base.Decider('MD5-timestamp') + # Use cached implicit dependencies by default. Can be overridden by specifying `--implicit-deps-changed` in the command line. + # http://scons.org/doc/production/HTML/scons-user/ch06s04.html + env_base.SetOption('implicit_cache', 1) + if (env_base['no_editor_splash']): env_base.Append(CPPDEFINES=['NO_EDITOR_SPLASH']) @@ -250,8 +254,8 @@ elif env_base['p'] != "": env_base["platform"] = selected_platform if selected_platform in platform_list: - - sys.path.append("./platform/" + selected_platform) + tmppath = "./platform/" + selected_platform + sys.path.insert(0, tmppath) import detect if "create" in dir(detect): env = detect.create(env_base) @@ -332,12 +336,18 @@ if selected_platform in platform_list: env.Append(CCFLAGS=['/WX']) else: # Rest of the world disable_nonessential_warnings = ['-Wno-sign-compare'] + shadow_local_warning = [] + + if 'gcc' in os.path.basename(env["CC"]): + version = methods.get_compiler_version(env) + if version != None and version[0] >= '7': + shadow_local_warning = ['-Wshadow-local'] if (env["warnings"] == 'extra'): - env.Append(CCFLAGS=['-Wall', '-Wextra']) + env.Append(CCFLAGS=['-Wall', '-Wextra'] + shadow_local_warning) elif (env["warnings"] == 'all'): - env.Append(CCFLAGS=['-Wall'] + disable_nonessential_warnings) + env.Append(CCFLAGS=['-Wall'] + shadow_local_warning + disable_nonessential_warnings) elif (env["warnings"] == 'moderate'): - env.Append(CCFLAGS=['-Wall', '-Wno-unused'] + disable_nonessential_warnings) + env.Append(CCFLAGS=['-Wall', '-Wno-unused'] + shadow_local_warning + disable_nonessential_warnings) else: # 'no' env.Append(CCFLAGS=['-w']) if (env["werror"]): @@ -377,7 +387,7 @@ if selected_platform in platform_list: suffix += env.extra_suffix - sys.path.remove("./platform/" + selected_platform) + sys.path.remove(tmppath) sys.modules.pop('detect') env.module_list = [] @@ -387,7 +397,7 @@ if selected_platform in platform_list: if not env['module_' + x + '_enabled']: continue tmppath = "./modules/" + x - sys.path.append(tmppath) + sys.path.insert(0, tmppath) env.current_module = x import config # can_build changed number of arguments between 3.0 (1) and 3.1 (2), diff --git a/core/allocators.h b/core/allocators.h deleted file mode 100644 index 8d4af7a9fb..0000000000 --- a/core/allocators.h +++ /dev/null @@ -1,195 +0,0 @@ -/*************************************************************************/ -/* allocators.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef ALLOCATORS_H -#define ALLOCATORS_H - -#include "core/os/memory.h" - -template <int PREALLOC_COUNT = 64, int MAX_HANDS = 8> -class BalloonAllocator { - - enum { - - USED_FLAG = (1 << 30), - USED_MASK = USED_FLAG - 1 - }; - - struct Balloon { - - Balloon *next; - Balloon *prev; - uint32_t hand; - }; - - struct Hand { - - int used; - int allocated; - Balloon *first; - Balloon *last; - }; - - Hand hands[MAX_HANDS]; - -public: - void *alloc(size_t p_size) { - - size_t max = (1 << MAX_HANDS); - ERR_FAIL_COND_V(p_size > max, NULL); - - unsigned int hand = 0; - - while (p_size > (size_t)(1 << hand)) - ++hand; - - Hand &h = hands[hand]; - - if (h.used == h.allocated) { - - for (int i = 0; i < PREALLOC_COUNT; i++) { - - Balloon *b = (Balloon *)memalloc(sizeof(Balloon) + (1 << hand)); - b->hand = hand; - if (h.last) { - - b->prev = h.last; - h.last->next = b; - h.last = b; - } else { - - b->prev = NULL; - h.last = b; - h.first = b; - } - } - - h.last->next = NULL; - h.allocated += PREALLOC_COUNT; - } - - Balloon *pick = h.last; - - ERR_FAIL_COND_V((pick->hand & USED_FLAG), NULL); - - // remove last - h.last = h.last->prev; - h.last->next = NULL; - - pick->next = h.first; - h.first->prev = pick; - pick->prev = NULL; - h.first = pick; - h.used++; - pick->hand |= USED_FLAG; - - return (void *)(pick + 1); - } - - void free(void *p_ptr) { - - Balloon *b = (Balloon *)p_ptr; - b -= 1; - - ERR_FAIL_COND(!(b->hand & USED_FLAG)); - - b->hand = b->hand & USED_MASK; // not used - int hand = b->hand; - - Hand &h = hands[hand]; - - if (b == h.first) - h.first = b->next; - - if (b->prev) - b->prev->next = b->next; - if (b->next) - b->next->prev = b->prev; - - if (h.last != b) { - h.last->next = b; - b->prev = h.last; - b->next = NULL; - h.last = b; - } - - h.used--; - - if (h.used <= (h.allocated - (PREALLOC_COUNT * 2))) { // this is done to ensure no alloc/free is done constantly - - for (int i = 0; i < PREALLOC_COUNT; i++) { - ERR_CONTINUE(h.last->hand & USED_FLAG); - - Balloon *new_last = h.last->prev; - if (new_last) - new_last->next = NULL; - memfree(h.last); - h.last = new_last; - } - h.allocated -= PREALLOC_COUNT; - } - } - - BalloonAllocator() { - - for (int i = 0; i < MAX_HANDS; i++) { - - hands[i].allocated = 0; - hands[i].used = 0; - hands[i].first = NULL; - hands[i].last = NULL; - } - } - - void clear() { - - for (int i = 0; i < MAX_HANDS; i++) { - - while (hands[i].first) { - - Balloon *b = hands[i].first; - hands[i].first = b->next; - memfree(b); - } - - hands[i].allocated = 0; - hands[i].used = 0; - hands[i].first = NULL; - hands[i].last = NULL; - } - } - - ~BalloonAllocator() { - - clear(); - } -}; - -#endif // ALLOCATORS_H diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp index f17d7372e2..f6828ea76a 100644 --- a/core/bind/core_bind.cpp +++ b/core/bind/core_bind.cpp @@ -225,8 +225,12 @@ int _OS::get_video_driver_count() const { return OS::get_singleton()->get_video_driver_count(); } -String _OS::get_video_driver_name(int p_driver) const { - return OS::get_singleton()->get_video_driver_name(p_driver); +String _OS::get_video_driver_name(VideoDriver p_driver) const { + return OS::get_singleton()->get_video_driver_name((int)p_driver); +} + +_OS::VideoDriver _OS::get_current_video_driver() const { + return (VideoDriver)OS::get_singleton()->get_current_video_driver(); } int _OS::get_audio_driver_count() const { @@ -1108,6 +1112,8 @@ void _OS::_bind_methods() { ClassDB::bind_method(D_METHOD("get_video_driver_count"), &_OS::get_video_driver_count); ClassDB::bind_method(D_METHOD("get_video_driver_name", "driver"), &_OS::get_video_driver_name); + ClassDB::bind_method(D_METHOD("get_current_video_driver"), &_OS::get_current_video_driver); + ClassDB::bind_method(D_METHOD("get_audio_driver_count"), &_OS::get_audio_driver_count); ClassDB::bind_method(D_METHOD("get_audio_driver_name", "driver"), &_OS::get_audio_driver_name); ClassDB::bind_method(D_METHOD("get_connected_midi_inputs"), &_OS::get_connected_midi_inputs); @@ -1276,6 +1282,9 @@ void _OS::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "window_position"), "set_window_position", "get_window_position"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "window_size"), "set_window_size", "get_window_size"); + BIND_ENUM_CONSTANT(VIDEO_DRIVER_GLES2); + BIND_ENUM_CONSTANT(VIDEO_DRIVER_GLES3); + BIND_ENUM_CONSTANT(DAY_SUNDAY); BIND_ENUM_CONSTANT(DAY_MONDAY); BIND_ENUM_CONSTANT(DAY_TUESDAY); diff --git a/core/bind/core_bind.h b/core/bind/core_bind.h index 1c8b985d73..f3bc4644d8 100644 --- a/core/bind/core_bind.h +++ b/core/bind/core_bind.h @@ -103,6 +103,11 @@ protected: static _OS *singleton; public: + enum VideoDriver { + VIDEO_DRIVER_GLES3, + VIDEO_DRIVER_GLES2, + }; + enum PowerState { POWERSTATE_UNKNOWN, /**< cannot determine power status */ POWERSTATE_ON_BATTERY, /**< Not plugged in, running on the battery */ @@ -152,7 +157,8 @@ public: Array get_fullscreen_mode_list(int p_screen = 0) const; virtual int get_video_driver_count() const; - virtual String get_video_driver_name(int p_driver) const; + virtual String get_video_driver_name(VideoDriver p_driver) const; + virtual VideoDriver get_current_video_driver() const; virtual int get_audio_driver_count() const; virtual String get_audio_driver_name(int p_driver) const; @@ -355,6 +361,7 @@ public: _OS(); }; +VARIANT_ENUM_CAST(_OS::VideoDriver); VARIANT_ENUM_CAST(_OS::PowerState); VARIANT_ENUM_CAST(_OS::Weekday); VARIANT_ENUM_CAST(_OS::Month); diff --git a/core/command_queue_mt.cpp b/core/command_queue_mt.cpp index 36d4b0a32f..2bdf02295c 100644 --- a/core/command_queue_mt.cpp +++ b/core/command_queue_mt.cpp @@ -97,7 +97,7 @@ tryagain: return false; } - dealloc_ptr += (size >> 1) + sizeof(uint32_t); + dealloc_ptr += (size >> 1) + 8; return true; } @@ -107,6 +107,7 @@ CommandQueueMT::CommandQueueMT(bool p_sync) { write_ptr = 0; dealloc_ptr = 0; mutex = Mutex::create(); + command_mem = (uint8_t *)memalloc(COMMAND_MEM_SIZE); for (int i = 0; i < SYNC_SEMAPHORES; i++) { @@ -128,4 +129,5 @@ CommandQueueMT::~CommandQueueMT() { memdelete(sync_sems[i].sem); } + memfree(command_mem); } diff --git a/core/command_queue_mt.h b/core/command_queue_mt.h index 3fd660a3db..59eabd8786 100644 --- a/core/command_queue_mt.h +++ b/core/command_queue_mt.h @@ -36,6 +36,7 @@ #include "core/os/semaphore.h" #include "core/simple_type.h" #include "core/typedefs.h" + /** @author Juan Linietsky <reduzio@gmail.com> */ @@ -254,6 +255,7 @@ unlock(); \ if (sync) sync->post(); \ ss->sem->wait(); \ + ss->in_use = false; \ } #define CMD_SYNC_TYPE(N) CommandSync##N<T, M COMMA(N) COMMA_SEP_LIST(TYPE_ARG, N)> @@ -270,6 +272,7 @@ unlock(); \ if (sync) sync->post(); \ ss->sem->wait(); \ + ss->in_use = false; \ } #define MAX_CMD_PARAMS 13 @@ -295,7 +298,6 @@ class CommandQueueMT { virtual void post() { sync_sem->sem->post(); - sync_sem->in_use = false; } }; @@ -318,7 +320,7 @@ class CommandQueueMT { SYNC_SEMAPHORES = 8 }; - uint8_t command_mem[COMMAND_MEM_SIZE]; + uint8_t *command_mem; uint32_t read_ptr; uint32_t write_ptr; uint32_t dealloc_ptr; @@ -330,7 +332,7 @@ class CommandQueueMT { T *allocate() { // alloc size is size+T+safeguard - uint32_t alloc_size = sizeof(T) + sizeof(uint32_t); + uint32_t alloc_size = ((sizeof(T) + 8 - 1) & ~(8 - 1)) + 8; tryagain: @@ -360,7 +362,7 @@ class CommandQueueMT { } // if this happens, it's a bug - ERR_FAIL_COND_V((COMMAND_MEM_SIZE - write_ptr) < sizeof(uint32_t), NULL); + ERR_FAIL_COND_V((COMMAND_MEM_SIZE - write_ptr) < 8, NULL); // zero means, wrap to beginning uint32_t *p = (uint32_t *)&command_mem[write_ptr]; @@ -372,12 +374,13 @@ class CommandQueueMT { // Allocate the size and the 'in use' bit. // First bit used to mark if command is still in use (1) // or if it has been destroyed and can be deallocated (0). + uint32_t size = (sizeof(T) + 8 - 1) & ~(8 - 1); uint32_t *p = (uint32_t *)&command_mem[write_ptr]; - *p = (sizeof(T) << 1) | 1; - write_ptr += sizeof(uint32_t); + *p = (size << 1) | 1; + write_ptr += 8; // allocate the command T *cmd = memnew_placement(&command_mem[write_ptr], T); - write_ptr += sizeof(T); + write_ptr += size; return cmd; } @@ -415,7 +418,7 @@ class CommandQueueMT { goto tryagain; } - read_ptr += sizeof(uint32_t); + read_ptr += 8; CommandBase *cmd = reinterpret_cast<CommandBase *>(&command_mem[read_ptr]); diff --git a/core/core_string_names.h b/core/core_string_names.h index 1a837cdc2e..6fea40e1b2 100644 --- a/core/core_string_names.h +++ b/core/core_string_names.h @@ -31,7 +31,7 @@ #ifndef CORE_STRING_NAMES_H #define CORE_STRING_NAMES_H -#include "core/string_db.h" +#include "core/string_name.h" class CoreStringNames { diff --git a/core/engine.cpp b/core/engine.cpp index 4dba41853d..9607dedb3c 100644 --- a/core/engine.cpp +++ b/core/engine.cpp @@ -98,6 +98,7 @@ Dictionary Engine::get_version_info() const { #else dict["patch"] = 0; #endif + dict["hex"] = VERSION_HEX; dict["status"] = VERSION_STATUS; dict["build"] = VERSION_BUILD; dict["year"] = VERSION_YEAR; diff --git a/core/error_macros.h b/core/error_macros.h index 60a0e8a7dc..3aa8ed4596 100644 --- a/core/error_macros.h +++ b/core/error_macros.h @@ -154,6 +154,20 @@ extern bool _err_error_exists; _err_error_exists = false; \ } while (0); // (*) +/** An index has failed if m_index >=m_size, the function exists. +* This function returns an error value, if returning Error, please select the most +* appropriate error condition from error_macros.h +*/ + +#define ERR_FAIL_UNSIGNED_INDEX_V(m_index, m_size, m_retval) \ + do { \ + if (unlikely((m_index) >= (m_size))) { \ + _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size)); \ + return m_retval; \ + } else \ + _err_error_exists = false; \ + } while (0); // (*) + /** Use this one if there is no sensible fallback, that is, the error is unrecoverable. * We'll return a null reference and try to keep running. */ diff --git a/core/global_constants.h b/core/global_constants.h index 47c1a4dafc..c798a3b9bc 100644 --- a/core/global_constants.h +++ b/core/global_constants.h @@ -31,7 +31,7 @@ #ifndef GLOBAL_CONSTANTS_H #define GLOBAL_CONSTANTS_H -#include "core/string_db.h" +#include "core/string_name.h" class GlobalConstants { public: diff --git a/core/hashfuncs.h b/core/hashfuncs.h index 811ce6264e..07d78dcbde 100644 --- a/core/hashfuncs.h +++ b/core/hashfuncs.h @@ -34,7 +34,7 @@ #include "core/math/math_defs.h" #include "core/math/math_funcs.h" #include "core/node_path.h" -#include "core/string_db.h" +#include "core/string_name.h" #include "core/typedefs.h" #include "core/ustring.h" diff --git a/core/image.cpp b/core/image.cpp index 91c3d05a29..5a287ca50e 100644 --- a/core/image.cpp +++ b/core/image.cpp @@ -1789,7 +1789,7 @@ Error Image::decompress() { _image_decompress_pvrtc(this); else if (format == FORMAT_ETC && _image_decompress_etc1) _image_decompress_etc1(this); - else if (format >= FORMAT_ETC2_R11 && format <= FORMAT_ETC2_RGB8A1 && _image_decompress_etc1) + else if (format >= FORMAT_ETC2_R11 && format <= FORMAT_ETC2_RGB8A1 && _image_decompress_etc2) _image_decompress_etc2(this); else return ERR_UNAVAILABLE; @@ -2901,15 +2901,15 @@ void Image::fix_alpha_edges() { if (dist >= closest_dist) continue; - const uint8_t *rp = &srcptr[(k * width + l) << 2]; + const uint8_t *rp2 = &srcptr[(k * width + l) << 2]; - if (rp[3] < alpha_threshold) + if (rp2[3] < alpha_threshold) continue; closest_dist = dist; - closest_color[0] = rp[0]; - closest_color[1] = rp[1]; - closest_color[2] = rp[2]; + closest_color[0] = rp2[0]; + closest_color[1] = rp2[1]; + closest_color[2] = rp2[2]; } } diff --git a/core/image.h b/core/image.h index b23f8cac46..872b84d565 100644 --- a/core/image.h +++ b/core/image.h @@ -32,8 +32,8 @@ #define IMAGE_H #include "core/color.h" -#include "core/dvector.h" #include "core/math/rect2.h" +#include "core/pool_vector.h" #include "core/resource.h" /** diff --git a/core/io/file_access_buffered.h b/core/io/file_access_buffered.h index 756045a674..4065d77c58 100644 --- a/core/io/file_access_buffered.h +++ b/core/io/file_access_buffered.h @@ -31,8 +31,8 @@ #ifndef FILE_ACCESS_BUFFERED_H #define FILE_ACCESS_BUFFERED_H -#include "core/dvector.h" #include "core/os/file_access.h" +#include "core/pool_vector.h" #include "core/ustring.h" class FileAccessBuffered : public FileAccess { diff --git a/core/io/file_access_buffered_fa.h b/core/io/file_access_buffered_fa.h index 5180f2344f..be960fbc25 100644 --- a/core/io/file_access_buffered_fa.h +++ b/core/io/file_access_buffered_fa.h @@ -54,7 +54,7 @@ class FileAccessBufferedFA : public FileAccessBuffered { cache.offset = p_offset; cache.buffer.resize(p_size); - // on dvector + // on PoolVector //PoolVector<uint8_t>::Write write = cache.buffer.write(); //f.get_buffer(write.ptrw(), p_size); diff --git a/core/io/file_access_zip.cpp b/core/io/file_access_zip.cpp index 66b911e83c..be28c9a877 100644 --- a/core/io/file_access_zip.cpp +++ b/core/io/file_access_zip.cpp @@ -168,10 +168,10 @@ bool ZipArchive::try_open_pack(const String &p_path) { zlib_filefunc_def io; - FileAccess *f = FileAccess::open(p_path, FileAccess::READ); - if (!f) + FileAccess *fa = FileAccess::open(p_path, FileAccess::READ); + if (!fa) return false; - io.opaque = f; + io.opaque = fa; io.zopen_file = godot_open; io.zread_file = godot_read; io.zwrite_file = godot_write; diff --git a/core/io/http_client.cpp b/core/io/http_client.cpp index b3fd814870..e5c6d2a4f2 100644 --- a/core/io/http_client.cpp +++ b/core/io/http_client.cpp @@ -278,6 +278,7 @@ void HTTPClient::close() { body_size = -1; body_left = 0; chunk_left = 0; + chunk_trailer_part = 0; read_until_eof = false; response_num = 0; handshaking = false; @@ -421,16 +422,16 @@ Error HTTPClient::poll() { chunked = false; body_left = 0; chunk_left = 0; + chunk_trailer_part = false; read_until_eof = false; response_str.clear(); response_headers.clear(); response_num = RESPONSE_OK; - // Per the HTTP 1.1 spec, keep-alive is the default, but in practice - // it's safe to assume it only if the explicit header is found, allowing - // to handle body-up-to-EOF responses on naive servers; that's what Curl - // and browsers do - bool keep_alive = false; + // Per the HTTP 1.1 spec, keep-alive is the default. + // Not following that specification breaks standard implemetations. + // Broken web servers should be fixed. + bool keep_alive = true; for (int i = 0; i < responses.size(); i++) { @@ -447,8 +448,8 @@ Error HTTPClient::poll() { if (encoding == "chunked") { chunked = true; } - } else if (s.begins_with("connection: keep-alive")) { - keep_alive = true; + } else if (s.begins_with("connection: close")) { + keep_alive = false; } if (i == 0 && responses[i].begins_with("HTTP")) { @@ -505,13 +506,37 @@ PoolByteArray HTTPClient::read_response_body_chunk() { ERR_FAIL_COND_V(status != STATUS_BODY, PoolByteArray()); + PoolByteArray ret; Error err = OK; if (chunked) { while (true) { - if (chunk_left == 0) { + if (chunk_trailer_part) { + // We need to consume the trailer part too or keep-alive will break + uint8_t b; + int rec = 0; + err = _get_http_data(&b, 1, rec); + + if (rec == 0) + break; + + chunk.push_back(b); + int cs = chunk.size(); + if ((cs >= 2 && chunk[cs - 2] == '\r' && chunk[cs - 1] == '\n')) { + if (cs == 2) { + // Finally over + chunk_trailer_part = false; + status = STATUS_CONNECTED; + chunk.clear(); + break; + } else { + // We do not process nor return the trailer data + chunk.clear(); + } + } + } else if (chunk_left == 0) { // Reading length uint8_t b; int rec = 0; @@ -525,7 +550,7 @@ PoolByteArray HTTPClient::read_response_body_chunk() { if (chunk.size() > 32) { ERR_PRINT("HTTP Invalid chunk hex len"); status = STATUS_CONNECTION_ERROR; - return PoolByteArray(); + break; } if (chunk.size() > 2 && chunk[chunk.size() - 2] == '\r' && chunk[chunk.size() - 1] == '\n') { @@ -543,22 +568,22 @@ PoolByteArray HTTPClient::read_response_body_chunk() { else { ERR_PRINT("HTTP Chunk len not in hex!!"); status = STATUS_CONNECTION_ERROR; - return PoolByteArray(); + break; } len <<= 4; len |= v; if (len > (1 << 24)) { ERR_PRINT("HTTP Chunk too big!! >16mb"); status = STATUS_CONNECTION_ERROR; - return PoolByteArray(); + break; } } if (len == 0) { // End reached! - status = STATUS_CONNECTED; + chunk_trailer_part = true; chunk.clear(); - return PoolByteArray(); + break; } chunk_left = len + 2; @@ -578,18 +603,13 @@ PoolByteArray HTTPClient::read_response_body_chunk() { if (chunk[chunk.size() - 2] != '\r' || chunk[chunk.size() - 1] != '\n') { ERR_PRINT("HTTP Invalid chunk terminator (not \\r\\n)"); status = STATUS_CONNECTION_ERROR; - return PoolByteArray(); + break; } - PoolByteArray ret; ret.resize(chunk.size() - 2); - { - PoolByteArray::Write w = ret.write(); - copymem(w.ptr(), chunk.ptr(), chunk.size() - 2); - } + PoolByteArray::Write w = ret.write(); + copymem(w.ptr(), chunk.ptr(), chunk.size() - 2); chunk.clear(); - - return ret; } break; @@ -599,45 +619,26 @@ PoolByteArray HTTPClient::read_response_body_chunk() { } else { int to_read = !read_until_eof ? MIN(body_left, read_chunk_size) : read_chunk_size; - PoolByteArray ret; ret.resize(to_read); int _offset = 0; - while (read_until_eof || to_read > 0) { + while (to_read > 0) { int rec = 0; { PoolByteArray::Write w = ret.write(); err = _get_http_data(w.ptr() + _offset, to_read, rec); } - if (rec < 0) { - if (to_read > 0) // Ended up reading less - ret.resize(_offset); + if (rec <= 0) { // Ended up reading less + ret.resize(_offset); break; } else { _offset += rec; + to_read -= rec; if (!read_until_eof) { body_left -= rec; - to_read -= rec; - } else { - if (rec < to_read) { - ret.resize(_offset); - err = ERR_FILE_EOF; - break; - } - ret.resize(_offset + to_read); } } - } - if (!read_until_eof) { - if (body_left == 0) { - status = STATUS_CONNECTED; - } - return ret; - } else { - if (err == ERR_FILE_EOF) { - err = OK; // EOF is expected here - close(); - return ret; - } + if (err != OK) + break; } } @@ -652,12 +653,12 @@ PoolByteArray HTTPClient::read_response_body_chunk() { status = STATUS_CONNECTION_ERROR; } - } else if (body_left == 0 && !chunked) { + } else if (body_left == 0 && !chunked && !read_until_eof) { status = STATUS_CONNECTED; } - return PoolByteArray(); + return ret; } HTTPClient::Status HTTPClient::get_status() const { @@ -719,6 +720,7 @@ HTTPClient::HTTPClient() { body_left = 0; read_until_eof = false; chunk_left = 0; + chunk_trailer_part = false; response_num = 0; ssl = false; blocking = false; diff --git a/core/io/http_client.h b/core/io/http_client.h index 1ad44d5f01..85ee1959a2 100644 --- a/core/io/http_client.h +++ b/core/io/http_client.h @@ -172,6 +172,7 @@ private: bool chunked; Vector<uint8_t> chunk; int chunk_left; + bool chunk_trailer_part; int body_size; int body_left; bool read_until_eof; diff --git a/core/io/marshalls.cpp b/core/io/marshalls.cpp index eec1c55744..5087a63b68 100644 --- a/core/io/marshalls.cpp +++ b/core/io/marshalls.cpp @@ -889,11 +889,11 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo if (buf) { encode_uint32(uint32_t(np.get_name_count()) | 0x80000000, buf); //for compatibility with the old format encode_uint32(np.get_subname_count(), buf + 4); - uint32_t flags = 0; + uint32_t np_flags = 0; if (np.is_absolute()) - flags |= 1; + np_flags |= 1; - encode_uint32(flags, buf + 8); + encode_uint32(np_flags, buf + 8); buf += 12; } diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp index 4d4134b745..d2c656b8eb 100644 --- a/core/io/resource_format_binary.cpp +++ b/core/io/resource_format_binary.cpp @@ -296,9 +296,9 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant &r_v) { } break; case VARIANT_OBJECT: { - uint32_t type = f->get_32(); + uint32_t objtype = f->get_32(); - switch (type) { + switch (objtype) { case OBJECT_EMPTY: { //do none @@ -317,7 +317,7 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant &r_v) { case OBJECT_EXTERNAL_RESOURCE: { //old file format, still around for compatibility - String type = get_unicode_string(); + String exttype = get_unicode_string(); String path = get_unicode_string(); if (path.find("://") == -1 && path.is_rel_path()) { @@ -329,7 +329,7 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant &r_v) { path = remaps[path]; } - RES res = ResourceLoader::load(path, type); + RES res = ResourceLoader::load(path, exttype); if (res.is_null()) { WARN_PRINT(String("Couldn't load resource: " + path).utf8().get_data()); @@ -346,7 +346,7 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant &r_v) { r_v = Variant(); } else { - String type = external_resources[erindex].type; + String exttype = external_resources[erindex].type; String path = external_resources[erindex].path; if (path.find("://") == -1 && path.is_rel_path()) { @@ -354,7 +354,7 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant &r_v) { path = ProjectSettings::get_singleton()->localize_path(res_path.get_base_dir().plus_file(path)); } - RES res = ResourceLoader::load(path, type); + RES res = ResourceLoader::load(path, exttype); if (res.is_null()) { WARN_PRINT(String("Couldn't load resource: " + path).utf8().get_data()); @@ -1314,8 +1314,7 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia } else { f->store_32(VARIANT_INT); - int val = p_property; - f->store_32(int32_t(val)); + f->store_32(int32_t(p_property)); } } break; @@ -1667,7 +1666,20 @@ void ResourceFormatSaverBinaryInstance::_find_resources(const Variant &p_variant if (E->get().usage & PROPERTY_USAGE_STORAGE) { - _find_resources(res->get(E->get().name)); + Variant value = res->get(E->get().name); + if (E->get().usage & PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT) { + RES sres = value; + if (sres.is_valid()) { + NonPersistentKey npk; + npk.base = res; + npk.property = E->get().name; + non_persistent_map[npk] = sres; + resource_set.insert(sres); + saved_resources.push_back(sres); + } + } else { + _find_resources(value); + } } } @@ -1811,7 +1823,17 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p if ((F->get().usage & PROPERTY_USAGE_STORAGE)) { Property p; p.name_idx = get_string_index(F->get().name); - p.value = E->get()->get(F->get().name); + + if (F->get().usage & PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT) { + NonPersistentKey npk; + npk.base = E->get(); + npk.property = F->get().name; + if (non_persistent_map.has(npk)) { + p.value = non_persistent_map[npk]; + } + } else { + p.value = E->get()->get(F->get().name); + } Variant default_value = ClassDB::class_get_default_property_value(E->get()->get_class(), F->get().name); diff --git a/core/io/resource_format_binary.h b/core/io/resource_format_binary.h index 8f2c48e745..c3c477b805 100644 --- a/core/io/resource_format_binary.h +++ b/core/io/resource_format_binary.h @@ -123,6 +123,14 @@ class ResourceFormatSaverBinaryInstance { FileAccess *f; String magic; Set<RES> resource_set; + + struct NonPersistentKey { //for resource properties generated on the fly + RES base; + StringName property; + bool operator<(const NonPersistentKey &p_key) const { return base == p_key.base ? property < p_key.property : base < p_key.base; } + }; + + Map<NonPersistentKey, RES> non_persistent_map; Map<StringName, int> string_map; Vector<StringName> strings; diff --git a/core/io/resource_import.cpp b/core/io/resource_importer.cpp index 63dc0b6a26..9327e000f5 100644 --- a/core/io/resource_import.cpp +++ b/core/io/resource_importer.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* resource_import.cpp */ +/* resource_importer.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,7 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "resource_import.h" +#include "resource_importer.h" #include "core/os/os.h" #include "core/variant_parser.h" diff --git a/core/io/resource_import.h b/core/io/resource_importer.h index 96dd7983e6..32c39a8085 100644 --- a/core/io/resource_import.h +++ b/core/io/resource_importer.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* resource_import.h */ +/* resource_importer.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef RESOURCE_IMPORT_H -#define RESOURCE_IMPORT_H +#ifndef RESOURCE_IMPORTER_H +#define RESOURCE_IMPORTER_H #include "core/io/resource_loader.h" @@ -110,4 +110,4 @@ public: virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = NULL) = 0; }; -#endif // RESOURCE_IMPORT_H +#endif // RESOURCE_IMPORTER_H diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp index 02e4d8dc7a..98309048bb 100644 --- a/core/io/resource_loader.cpp +++ b/core/io/resource_loader.cpp @@ -30,7 +30,7 @@ #include "resource_loader.h" -#include "core/io/resource_import.h" +#include "core/io/resource_importer.h" #include "core/os/file_access.h" #include "core/os/os.h" #include "core/path_remap.h" @@ -55,7 +55,7 @@ Error ResourceInteractiveLoader::wait() { ResourceInteractiveLoader::~ResourceInteractiveLoader() { if (path_loading != String()) { - ResourceLoader::_remove_from_loading_map(path_loading); + ResourceLoader::_remove_from_loading_map_and_thread(path_loading, path_loading_thread); } } @@ -293,10 +293,14 @@ bool ResourceLoader::_add_to_loading_map(const String &p_path) { loading_map_mutex->lock(); } - if (loading_map.has(p_path)) { + LoadingMapKey key; + key.path = p_path; + key.thread = Thread::get_caller_id(); + + if (loading_map.has(key)) { success = false; } else { - loading_map[p_path] = true; + loading_map[key] = true; success = true; } @@ -312,7 +316,27 @@ void ResourceLoader::_remove_from_loading_map(const String &p_path) { loading_map_mutex->lock(); } - loading_map.erase(p_path); + LoadingMapKey key; + key.path = p_path; + key.thread = Thread::get_caller_id(); + + loading_map.erase(key); + + if (loading_map_mutex) { + loading_map_mutex->unlock(); + } +} + +void ResourceLoader::_remove_from_loading_map_and_thread(const String &p_path, Thread::ID p_thread) { + if (loading_map_mutex) { + loading_map_mutex->lock(); + } + + LoadingMapKey key; + key.path = p_path; + key.thread = p_thread; + + loading_map.erase(key); if (loading_map_mutex) { loading_map_mutex->unlock(); @@ -471,6 +495,7 @@ Ref<ResourceInteractiveLoader> ResourceLoader::load_interactive(const String &p_ ril->resource = res_cached; ril->path_loading = local_path; + ril->path_loading_thread = Thread::get_caller_id(); return ril; } } @@ -499,6 +524,7 @@ Ref<ResourceInteractiveLoader> ResourceLoader::load_interactive(const String &p_ if (!p_no_cache) { ril->set_local_path(local_path); ril->path_loading = local_path; + ril->path_loading_thread = Thread::get_caller_id(); } if (xl_remapped) @@ -879,9 +905,9 @@ bool ResourceLoader::add_custom_resource_format_loader(String script_path) { void ResourceLoader::remove_custom_resource_format_loader(String script_path) { - Ref<ResourceFormatLoader> loader = _find_custom_resource_format_loader(script_path); - if (loader.is_valid()) - remove_resource_format_loader(loader); + Ref<ResourceFormatLoader> custom_loader = _find_custom_resource_format_loader(script_path); + if (custom_loader.is_valid()) + remove_resource_format_loader(custom_loader); } void ResourceLoader::add_custom_loaders() { @@ -919,7 +945,7 @@ void ResourceLoader::remove_custom_loaders() { } Mutex *ResourceLoader::loading_map_mutex = NULL; -HashMap<String, int> ResourceLoader::loading_map; +HashMap<ResourceLoader::LoadingMapKey, int, ResourceLoader::LoadingMapKeyHasher> ResourceLoader::loading_map; void ResourceLoader::initialize() { #ifndef NO_THREADS @@ -929,9 +955,9 @@ void ResourceLoader::initialize() { void ResourceLoader::finalize() { #ifndef NO_THREADS - const String *K = NULL; + const LoadingMapKey *K = NULL; while ((K = loading_map.next(K))) { - ERR_PRINTS("Exited while resource is being loaded: " + *K); + ERR_PRINTS("Exited while resource is being loaded: " + K->path); } loading_map.clear(); memdelete(loading_map_mutex); diff --git a/core/io/resource_loader.h b/core/io/resource_loader.h index 622b74a998..70eb1a3de0 100644 --- a/core/io/resource_loader.h +++ b/core/io/resource_loader.h @@ -31,8 +31,8 @@ #ifndef RESOURCE_LOADER_H #define RESOURCE_LOADER_H +#include "core/os/thread.h" #include "core/resource.h" - /** @author Juan Linietsky <reduzio@gmail.com> */ @@ -42,6 +42,7 @@ class ResourceInteractiveLoader : public Reference { GDCLASS(ResourceInteractiveLoader, Reference); friend class ResourceLoader; String path_loading; + Thread::ID path_loading_thread; protected: static void _bind_methods(); @@ -121,10 +122,25 @@ class ResourceLoader { static Ref<ResourceFormatLoader> _find_custom_resource_format_loader(String path); static Mutex *loading_map_mutex; - static HashMap<String, int> loading_map; + + //used to track paths being loaded in a thread, avoids cyclic recursion + struct LoadingMapKey { + String path; + Thread::ID thread; + bool operator==(const LoadingMapKey &p_key) const { + return (thread == p_key.thread && path == p_key.path); + } + }; + struct LoadingMapKeyHasher { + + static _FORCE_INLINE_ uint32_t hash(const LoadingMapKey &p_key) { return p_key.path.hash() + HashMapHasherDefault::hash(p_key.thread); } + }; + + static HashMap<LoadingMapKey, int, LoadingMapKeyHasher> loading_map; static bool _add_to_loading_map(const String &p_path); static void _remove_from_loading_map(const String &p_path); + static void _remove_from_loading_map_and_thread(const String &p_path, Thread::ID p_thread); public: static Ref<ResourceInteractiveLoader> load_interactive(const String &p_path, const String &p_type_hint = "", bool p_no_cache = false, Error *r_error = NULL); diff --git a/core/io/resource_saver.cpp b/core/io/resource_saver.cpp index 279788796c..c992e2bf94 100644 --- a/core/io/resource_saver.cpp +++ b/core/io/resource_saver.cpp @@ -233,9 +233,9 @@ bool ResourceSaver::add_custom_resource_format_saver(String script_path) { void ResourceSaver::remove_custom_resource_format_saver(String script_path) { - Ref<ResourceFormatSaver> saver = _find_custom_resource_format_saver(script_path); - if (saver.is_valid()) - remove_resource_format_saver(saver); + Ref<ResourceFormatSaver> custom_saver = _find_custom_resource_format_saver(script_path); + if (custom_saver.is_valid()) + remove_resource_format_saver(custom_saver); } void ResourceSaver::add_custom_savers() { diff --git a/core/list.h b/core/list.h index dd4ea3bd89..c26aad6463 100644 --- a/core/list.h +++ b/core/list.h @@ -32,7 +32,7 @@ #define GLOBALS_LIST_H #include "core/os/memory.h" -#include "core/sort.h" +#include "core/sort_array.h" /** * Generic Templatized Linked List Implementation. diff --git a/core/math/a_star.cpp b/core/math/a_star.cpp index b885a06834..6c3b84d49a 100644 --- a/core/math/a_star.cpp +++ b/core/math/a_star.cpp @@ -97,11 +97,14 @@ void AStar::remove_point(int p_id) { Point *p = points[p_id]; - for (Set<Point *>::Element *E = p->neighbours.front(); E; E = E->next()) { - - Segment s(p_id, E->get()->id); - segments.erase(s); - E->get()->neighbours.erase(p); + Map<int, Point *>::Element *PE = points.front(); + while (PE) { + for (Set<Point *>::Element *E = PE->get()->neighbours.front(); E; E = E->next()) { + Segment s(p_id, E->get()->id); + segments.erase(s); + E->get()->neighbours.erase(p); + } + PE = PE->next(); } memdelete(p); @@ -371,14 +374,14 @@ PoolVector<Vector3> AStar::get_point_path(int p_from_id, int p_to_id) { { PoolVector<Vector3>::Write w = path.write(); - Point *p = end_point; + Point *p2 = end_point; int idx = pc - 1; - while (p != begin_point) { - w[idx--] = p->pos; - p = p->prev_point; + while (p2 != begin_point) { + w[idx--] = p2->pos; + p2 = p2->prev_point; } - w[0] = p->pos; // Assign first + w[0] = p2->pos; // Assign first } return path; diff --git a/core/math/matrix3.cpp b/core/math/basis.cpp index 0aa67078fb..7f60b7962c 100644 --- a/core/math/matrix3.cpp +++ b/core/math/basis.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* matrix3.cpp */ +/* basis.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,7 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "matrix3.h" +#include "basis.h" #include "core/math/math_funcs.h" #include "core/os/copymem.h" @@ -258,7 +258,7 @@ Vector3 Basis::get_scale_abs() const { } Vector3 Basis::get_scale_local() const { - real_t det_sign = determinant() > 0 ? 1 : -1; + real_t det_sign = SGN(determinant()); return det_sign * Vector3(elements[0].length(), elements[1].length(), elements[2].length()); } @@ -284,7 +284,7 @@ Vector3 Basis::get_scale() const { // matrix elements. // // The rotation part of this decomposition is returned by get_rotation* functions. - real_t det_sign = determinant() > 0 ? 1 : -1; + real_t det_sign = SGN(determinant()); return det_sign * Vector3( Vector3(elements[0][0], elements[1][0], elements[2][0]).length(), Vector3(elements[0][1], elements[1][1], elements[2][1]).length(), diff --git a/core/math/matrix3.h b/core/math/basis.h index e7d6ab4522..128e56b494 100644 --- a/core/math/matrix3.h +++ b/core/math/basis.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* matrix3.h */ +/* basis.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -31,8 +31,8 @@ // Circular dependency between Vector3 and Basis :/ #include "core/math/vector3.h" -#ifndef MATRIX3_H -#define MATRIX3_H +#ifndef BASIS_H +#define BASIS_H #include "core/math/quat.h" @@ -341,4 +341,4 @@ real_t Basis::determinant() const { elements[1][0] * (elements[0][1] * elements[2][2] - elements[2][1] * elements[0][2]) + elements[2][0] * (elements[0][1] * elements[1][2] - elements[1][1] * elements[0][2]); } -#endif +#endif // BASIS_H diff --git a/core/math/bsp_tree.h b/core/math/bsp_tree.h index 0af532a2d5..a7a3697990 100644 --- a/core/math/bsp_tree.h +++ b/core/math/bsp_tree.h @@ -31,11 +31,11 @@ #ifndef BSP_TREE_H #define BSP_TREE_H -#include "core/dvector.h" #include "core/math/aabb.h" #include "core/math/face3.h" #include "core/math/plane.h" #include "core/method_ptrcall.h" +#include "core/pool_vector.h" #include "core/variant.h" #include "core/vector.h" /** diff --git a/core/math/expression.cpp b/core/math/expression.cpp index 61e5154f44..99251d80e3 100644 --- a/core/math/expression.cpp +++ b/core/math/expression.cpp @@ -1264,10 +1264,10 @@ Expression::ENode *Expression::_parse_expression() { } str_ofs = cofs; //revert //parse an expression - ENode *expr = _parse_expression(); - if (!expr) + ENode *subexpr = _parse_expression(); + if (!subexpr) return NULL; - dn->dict.push_back(expr); + dn->dict.push_back(subexpr); _get_token(tk); if (tk.type != TK_COLON) { @@ -1275,11 +1275,11 @@ Expression::ENode *Expression::_parse_expression() { return NULL; } - expr = _parse_expression(); - if (!expr) + subexpr = _parse_expression(); + if (!subexpr) return NULL; - dn->dict.push_back(expr); + dn->dict.push_back(subexpr); cofs = str_ofs; _get_token(tk); @@ -1308,10 +1308,10 @@ Expression::ENode *Expression::_parse_expression() { } str_ofs = cofs; //revert //parse an expression - ENode *expr = _parse_expression(); - if (!expr) + ENode *subexpr = _parse_expression(); + if (!subexpr) return NULL; - an->array.push_back(expr); + an->array.push_back(subexpr); cofs = str_ofs; _get_token(tk); @@ -1355,25 +1355,25 @@ Expression::ENode *Expression::_parse_expression() { while (true) { - int cofs = str_ofs; + int cofs2 = str_ofs; _get_token(tk); if (tk.type == TK_PARENTHESIS_CLOSE) { break; } - str_ofs = cofs; //revert + str_ofs = cofs2; //revert //parse an expression - ENode *expr = _parse_expression(); - if (!expr) + ENode *subexpr = _parse_expression(); + if (!subexpr) return NULL; - func_call->arguments.push_back(expr); + func_call->arguments.push_back(subexpr); - cofs = str_ofs; + cofs2 = str_ofs; _get_token(tk); if (tk.type == TK_COMMA) { //all good } else if (tk.type == TK_PARENTHESIS_CLOSE) { - str_ofs = cofs; + str_ofs = cofs2; } else { _set_error("Expected ',' or ')'"); } @@ -1444,11 +1444,11 @@ Expression::ENode *Expression::_parse_expression() { } str_ofs = cofs; //revert //parse an expression - ENode *expr = _parse_expression(); - if (!expr) + ENode *subexpr = _parse_expression(); + if (!subexpr) return NULL; - constructor->arguments.push_back(expr); + constructor->arguments.push_back(subexpr); cofs = str_ofs; _get_token(tk); @@ -1485,11 +1485,11 @@ Expression::ENode *Expression::_parse_expression() { } str_ofs = cofs; //revert //parse an expression - ENode *expr = _parse_expression(); - if (!expr) + ENode *subexpr = _parse_expression(); + if (!subexpr) return NULL; - bifunc->arguments.push_back(expr); + bifunc->arguments.push_back(subexpr); cofs = str_ofs; _get_token(tk); @@ -1584,25 +1584,25 @@ Expression::ENode *Expression::_parse_expression() { while (true) { - int cofs = str_ofs; + int cofs3 = str_ofs; _get_token(tk); if (tk.type == TK_PARENTHESIS_CLOSE) { break; } - str_ofs = cofs; //revert + str_ofs = cofs3; //revert //parse an expression - ENode *expr = _parse_expression(); - if (!expr) + ENode *subexpr = _parse_expression(); + if (!subexpr) return NULL; - func_call->arguments.push_back(expr); + func_call->arguments.push_back(subexpr); - cofs = str_ofs; + cofs3 = str_ofs; _get_token(tk); if (tk.type == TK_COMMA) { //all good } else if (tk.type == TK_PARENTHESIS_CLOSE) { - str_ofs = cofs; + str_ofs = cofs3; } else { _set_error("Expected ',' or ')'"); } @@ -1902,7 +1902,7 @@ bool Expression::_execute(const Array &p_inputs, Object *p_instance, Expression: Variant b; if (op->nodes[1]) { - bool ret = _execute(p_inputs, p_instance, op->nodes[1], b, r_error_str); + ret = _execute(p_inputs, p_instance, op->nodes[1], b, r_error_str); if (ret) return true; } @@ -2070,7 +2070,7 @@ bool Expression::_execute(const Array &p_inputs, Object *p_instance, Expression: for (int i = 0; i < call->arguments.size(); i++) { Variant value; - bool ret = _execute(p_inputs, p_instance, call->arguments[i], value, r_error_str); + ret = _execute(p_inputs, p_instance, call->arguments[i], value, r_error_str); if (ret) return true; diff --git a/core/math/face3.h b/core/math/face3.h index 1a00851eab..184e80ff77 100644 --- a/core/math/face3.h +++ b/core/math/face3.h @@ -241,13 +241,13 @@ bool Face3::intersects_aabb2(const AABB &p_aabb) const { real_t minT = 1e20, maxT = -1e20; for (int k = 0; k < 3; k++) { - real_t d = axis.dot(vertex[k]); + real_t vert_d = axis.dot(vertex[k]); - if (d > maxT) - maxT = d; + if (vert_d > maxT) + maxT = vert_d; - if (d < minT) - minT = d; + if (vert_d < minT) + minT = vert_d; } if (maxB < minT || maxT < minB) diff --git a/core/math/geometry.h b/core/math/geometry.h index 29493516b8..f927a63ed5 100644 --- a/core/math/geometry.h +++ b/core/math/geometry.h @@ -31,12 +31,12 @@ #ifndef GEOMETRY_H #define GEOMETRY_H -#include "core/dvector.h" #include "core/math/face3.h" #include "core/math/rect2.h" #include "core/math/triangulate.h" #include "core/math/vector3.h" #include "core/object.h" +#include "core/pool_vector.h" #include "core/print_string.h" #include "core/vector.h" diff --git a/core/math/math_funcs.h b/core/math/math_funcs.h index ea0bfd88cc..629002ced6 100644 --- a/core/math/math_funcs.h +++ b/core/math/math_funcs.h @@ -242,8 +242,8 @@ public: static void randomize(); static uint32_t rand_from_seed(uint64_t *seed); static uint32_t rand(); - static _ALWAYS_INLINE_ double randf() { return (double)rand() / (double)Math::RANDOM_MAX; } - static _ALWAYS_INLINE_ float randd() { return (float)rand() / (float)Math::RANDOM_MAX; } + static _ALWAYS_INLINE_ double randd() { return (double)rand() / (double)Math::RANDOM_MAX; } + static _ALWAYS_INLINE_ float randf() { return (float)rand() / (float)Math::RANDOM_MAX; } static double random(double from, double to); static float random(float from, float to); diff --git a/core/math/octree.h b/core/math/octree.h index 36a77663f4..d6fc9776bc 100644 --- a/core/math/octree.h +++ b/core/math/octree.h @@ -916,34 +916,34 @@ void Octree<T, use_pairs, AL>::move(OctreeElementID p_id, const AABB &p_aabb) { pass++; - for (typename List<typename Element::OctantOwner, AL>::Element *E = owners.front(); E;) { + for (typename List<typename Element::OctantOwner, AL>::Element *F = owners.front(); F;) { - Octant *o = E->get().octant; - typename List<typename Element::OctantOwner, AL>::Element *N = E->next(); + Octant *o = F->get().octant; + typename List<typename Element::OctantOwner, AL>::Element *N = F->next(); /* if (!use_pairs) - o->elements.erase( E->get().E ); + o->elements.erase( F->get().E ); */ if (use_pairs && e.pairable) - o->pairable_elements.erase(E->get().E); + o->pairable_elements.erase(F->get().E); else - o->elements.erase(E->get().E); + o->elements.erase(F->get().E); if (_remove_element_from_octant(&e, o, common_parent->parent)) { - owners.erase(E); + owners.erase(F); } - E = N; + F = N; } if (use_pairs) { //unpair child elements in anything that survived - for (typename List<typename Element::OctantOwner, AL>::Element *E = owners.front(); E; E = E->next()) { + for (typename List<typename Element::OctantOwner, AL>::Element *F = owners.front(); F; F = F->next()) { - Octant *o = E->get().octant; + Octant *o = F->get().octant; // erase children pairs, unref ONCE pass++; diff --git a/core/math/quat.cpp b/core/math/quat.cpp index c1e45f36f0..6833d5de55 100644 --- a/core/math/quat.cpp +++ b/core/math/quat.cpp @@ -30,7 +30,7 @@ #include "quat.h" -#include "core/math/matrix3.h" +#include "core/math/basis.h" #include "core/print_string.h" // set_euler_xyz expects a vector containing the Euler angles in the format diff --git a/core/math/quick_hull.cpp b/core/math/quick_hull.cpp index 1aa345db1f..bc2b4e6fe0 100644 --- a/core/math/quick_hull.cpp +++ b/core/math/quick_hull.cpp @@ -438,12 +438,12 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry::MeshData &r_me } // remove all edge connections to this face - for (Map<Edge, RetFaceConnect>::Element *E = ret_edges.front(); E; E = E->next()) { - if (E->get().left == O) - E->get().left = NULL; + for (Map<Edge, RetFaceConnect>::Element *G = ret_edges.front(); G; G = G->next()) { + if (G->get().left == O) + G->get().left = NULL; - if (E->get().right == O) - E->get().right = NULL; + if (G->get().right == O) + G->get().right = NULL; } ret_edges.erase(F); //remove the edge diff --git a/core/math/random_pcg.h b/core/math/random_pcg.h index ef69bf7120..2a69d43904 100644 --- a/core/math/random_pcg.h +++ b/core/math/random_pcg.h @@ -45,7 +45,10 @@ public: RandomPCG(uint64_t seed = DEFAULT_SEED, uint64_t inc = PCG_DEFAULT_INC_64); - _FORCE_INLINE_ void seed(uint64_t seed) { pcg.state = seed; } + _FORCE_INLINE_ void seed(uint64_t seed) { + pcg.state = seed; + pcg32_random_r(&pcg); // Force changing internal state to avoid initial 0 + } _FORCE_INLINE_ uint64_t get_seed() { return pcg.state; } void randomize(); diff --git a/core/math/transform.h b/core/math/transform.h index 9b323a6f0f..2f43f6b035 100644 --- a/core/math/transform.h +++ b/core/math/transform.h @@ -32,7 +32,7 @@ #define TRANSFORM_H #include "core/math/aabb.h" -#include "core/math/matrix3.h" +#include "core/math/basis.h" #include "core/math/plane.h" /** diff --git a/core/math/transform_2d.cpp b/core/math/transform_2d.cpp index 295e60babb..7d00158f3d 100644 --- a/core/math/transform_2d.cpp +++ b/core/math/transform_2d.cpp @@ -80,13 +80,14 @@ real_t Transform2D::get_rotation() const { } void Transform2D::set_rotation(real_t p_rot) { - + Size2 scale = get_scale(); real_t cr = Math::cos(p_rot); real_t sr = Math::sin(p_rot); elements[0][0] = cr; elements[0][1] = sr; elements[1][0] = -sr; elements[1][1] = cr; + set_scale(scale); } Transform2D::Transform2D(real_t p_rot, const Vector2 &p_pos) { @@ -101,10 +102,17 @@ Transform2D::Transform2D(real_t p_rot, const Vector2 &p_pos) { } Size2 Transform2D::get_scale() const { - real_t det_sign = basis_determinant() > 0 ? 1 : -1; + real_t det_sign = SGN(basis_determinant()); return Size2(elements[0].length(), det_sign * elements[1].length()); } +void Transform2D::set_scale(Size2 &p_scale) { + elements[0].normalize(); + elements[1].normalize(); + elements[0] *= p_scale.x; + elements[1] *= p_scale.y; +} + void Transform2D::scale(const Size2 &p_scale) { scale_basis(p_scale); elements[2] *= p_scale; diff --git a/core/math/transform_2d.h b/core/math/transform_2d.h index 507e6a16eb..b9e7a36fb3 100644 --- a/core/math/transform_2d.h +++ b/core/math/transform_2d.h @@ -81,6 +81,7 @@ struct Transform2D { real_t basis_determinant() const; Size2 get_scale() const; + void set_scale(Size2 &p_scale); _FORCE_INLINE_ const Vector2 &get_origin() const { return elements[2]; } _FORCE_INLINE_ void set_origin(const Vector2 &p_origin) { elements[2] = p_origin; } diff --git a/core/math/triangle_mesh.cpp b/core/math/triangle_mesh.cpp index cdf3d16b72..83784a1fa7 100644 --- a/core/math/triangle_mesh.cpp +++ b/core/math/triangle_mesh.cpp @@ -30,7 +30,7 @@ #include "triangle_mesh.h" -#include "core/sort.h" +#include "core/sort_array.h" int TriangleMesh::_create_bvh(BVH *p_bvh, BVH **p_bb, int p_from, int p_size, int p_depth, int &max_depth, int &max_alloc) { diff --git a/core/math/vector3.cpp b/core/math/vector3.cpp index b2e89ac7b8..1c28934422 100644 --- a/core/math/vector3.cpp +++ b/core/math/vector3.cpp @@ -30,7 +30,7 @@ #include "vector3.h" -#include "core/math/matrix3.h" +#include "core/math/basis.h" void Vector3::rotate(const Vector3 &p_axis, real_t p_phi) { diff --git a/core/math/vector3.h b/core/math/vector3.h index b0eef35635..8d6e093c4c 100644 --- a/core/math/vector3.h +++ b/core/math/vector3.h @@ -151,7 +151,7 @@ struct Vector3 { }; // Should be included after class definition, otherwise we get circular refs -#include "core/math/matrix3.h" +#include "core/math/basis.h" Vector3 Vector3::cross(const Vector3 &p_b) const { diff --git a/core/node_path.h b/core/node_path.h index 17b1435723..24725123d6 100644 --- a/core/node_path.h +++ b/core/node_path.h @@ -31,7 +31,7 @@ #ifndef NODE_PATH_H #define NODE_PATH_H -#include "core/string_db.h" +#include "core/string_name.h" #include "core/ustring.h" /** diff --git a/core/object.cpp b/core/object.cpp index 05e661baab..4e0416ccb0 100644 --- a/core/object.cpp +++ b/core/object.cpp @@ -703,40 +703,38 @@ Variant Object::_call_deferred_bind(const Variant **p_args, int p_argcount, Vari } #ifdef DEBUG_ENABLED -static bool _test_call_error(const StringName &p_func, const Variant::CallError &error) { +static void _test_call_error(const StringName &p_func, const Variant::CallError &error) { switch (error.error) { case Variant::CallError::CALL_OK: - return true; case Variant::CallError::CALL_ERROR_INVALID_METHOD: - return false; + break; case Variant::CallError::CALL_ERROR_INVALID_ARGUMENT: { ERR_EXPLAIN("Error Calling Function: " + String(p_func) + " - Invalid type for argument " + itos(error.argument) + ", expected " + Variant::get_type_name(error.expected)); - ERR_FAIL_V(true); - } break; + ERR_FAIL(); + break; + } case Variant::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS: { ERR_EXPLAIN("Error Calling Function: " + String(p_func) + " - Too many arguments, expected " + itos(error.argument)); - ERR_FAIL_V(true); - - } break; + ERR_FAIL(); + break; + } case Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS: { ERR_EXPLAIN("Error Calling Function: " + String(p_func) + " - Too few arguments, expected " + itos(error.argument)); - ERR_FAIL_V(true); - - } break; - case Variant::CallError::CALL_ERROR_INSTANCE_IS_NULL: { - } //? + ERR_FAIL(); + break; + } + case Variant::CallError::CALL_ERROR_INSTANCE_IS_NULL: + break; } - - return true; } #else -#define _test_call_error(m_str, m_err) ((m_err.error == Variant::CallError::CALL_ERROR_INVALID_METHOD) ? false : true) +#define _test_call_error(m_str, m_err) #endif @@ -1247,7 +1245,7 @@ Error Object::emit_signal(const StringName &p_name, const Variant **p_args, int bool disconnect = c.flags & CONNECT_ONESHOT; #ifdef TOOLS_ENABLED if (disconnect && (c.flags & CONNECT_PERSIST) && Engine::get_singleton()->is_editor_hint()) { - //this signal was connected from the editor, and is being edited. just dont disconnect for now + //this signal was connected from the editor, and is being edited. just don't disconnect for now disconnect = false; } #endif @@ -1929,6 +1927,13 @@ bool Object::has_script_instance_binding(int p_script_language_index) { return _script_instance_bindings[p_script_language_index] != NULL; } +void Object::set_script_instance_binding(int p_script_language_index, void *p_data) { +#ifdef DEBUG_ENABLED + CRASH_COND(_script_instance_bindings[p_script_language_index] != NULL); +#endif + _script_instance_bindings[p_script_language_index] = p_data; +} + Object::Object() { _class_ptr = NULL; @@ -1992,9 +1997,11 @@ Object::~Object() { _instance_ID = 0; _predelete_ok = 2; - for (int i = 0; i < MAX_SCRIPT_INSTANCE_BINDINGS; i++) { - if (_script_instance_bindings[i]) { - ScriptServer::get_language(i)->free_instance_binding_data(_script_instance_bindings[i]); + if (!ScriptServer::are_languages_finished()) { + for (int i = 0; i < MAX_SCRIPT_INSTANCE_BINDINGS; i++) { + if (_script_instance_bindings[i]) { + ScriptServer::get_language(i)->free_instance_binding_data(_script_instance_bindings[i]); + } } } } diff --git a/core/object.h b/core/object.h index 5bfef8a439..e8a6178052 100644 --- a/core/object.h +++ b/core/object.h @@ -119,6 +119,7 @@ enum PropertyUsageFlags { PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE = 1 << 21, // If the object is duplicated also this property will be duplicated PROPERTY_USAGE_HIGH_END_GFX = 1 << 22, PROPERTY_USAGE_NODE_PATH_FROM_SCENE_ROOT = 1 << 23, + PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT = 1 << 24, PROPERTY_USAGE_DEFAULT = PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_NETWORK, PROPERTY_USAGE_DEFAULT_INTL = PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_NETWORK | PROPERTY_USAGE_INTERNATIONALIZED, @@ -730,6 +731,7 @@ public: //used by script languages to store binding data void *get_script_instance_binding(int p_script_language_index); bool has_script_instance_binding(int p_script_language_index); + void set_script_instance_binding(int p_script_language_index, void *p_data); void clear_internal_resource_paths(); diff --git a/core/os/input_event.cpp b/core/os/input_event.cpp index 1e0e83c8d2..24ec8a1963 100644 --- a/core/os/input_event.cpp +++ b/core/os/input_event.cpp @@ -749,6 +749,15 @@ bool InputEventJoypadButton::action_match(const Ref<InputEvent> &p_event, bool * return match; } +bool InputEventJoypadButton::shortcut_match(const Ref<InputEvent> &p_event) const { + + Ref<InputEventJoypadButton> button = p_event; + if (button.is_null()) + return false; + + return button_index == button->button_index; +} + String InputEventJoypadButton::as_text() const { return "InputEventJoypadButton : button_index=" + itos(button_index) + ", pressed=" + (pressed ? "true" : "false") + ", pressure=" + String(Variant(pressure)); @@ -950,11 +959,10 @@ bool InputEventAction::is_pressed() const { } bool InputEventAction::shortcut_match(const Ref<InputEvent> &p_event) const { - Ref<InputEventKey> event = p_event; - if (event.is_null()) + if (p_event.is_null()) return false; - return event->is_action(action); + return p_event->is_action(action); } bool InputEventAction::is_action(const StringName &p_action) const { diff --git a/core/os/input_event.h b/core/os/input_event.h index db31055b5f..a6a7012298 100644 --- a/core/os/input_event.h +++ b/core/os/input_event.h @@ -400,6 +400,7 @@ public: float get_pressure() const; virtual bool action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float p_deadzone) const; + virtual bool shortcut_match(const Ref<InputEvent> &p_event) const; virtual bool is_action_type() const { return true; } virtual String as_text() const; diff --git a/core/os/os.h b/core/os/os.h index 20a3494e11..396555970a 100644 --- a/core/os/os.h +++ b/core/os/os.h @@ -45,12 +45,6 @@ @author Juan Linietsky <reduzio@gmail.com> */ -enum VideoDriver { - VIDEO_DRIVER_GLES3, - VIDEO_DRIVER_GLES2, - VIDEO_DRIVER_MAX, -}; - class OS { static OS *singleton; @@ -184,9 +178,16 @@ public: virtual VideoMode get_video_mode(int p_screen = 0) const = 0; virtual void get_fullscreen_mode_list(List<VideoMode> *p_list, int p_screen = 0) const = 0; + enum VideoDriver { + VIDEO_DRIVER_GLES3, + VIDEO_DRIVER_GLES2, + VIDEO_DRIVER_MAX, + }; + virtual int get_video_driver_count() const; virtual const char *get_video_driver_name(int p_driver) const; virtual int get_current_video_driver() const = 0; + virtual int get_audio_driver_count() const; virtual const char *get_audio_driver_name(int p_driver) const; diff --git a/core/os/shell.cpp b/core/os/shell.cpp deleted file mode 100644 index a859241cb6..0000000000 --- a/core/os/shell.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/*************************************************************************/ -/* shell.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "shell.h" - -Shell *Shell::singleton = NULL; - -Shell *Shell::get_singleton() { - - return singleton; -} - -Shell::~Shell() { -} - -Shell::Shell() { - - singleton = this; -} diff --git a/core/os/shell.h b/core/os/shell.h deleted file mode 100644 index c1bd995b5b..0000000000 --- a/core/os/shell.h +++ /dev/null @@ -1,52 +0,0 @@ -/*************************************************************************/ -/* shell.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef SHELL_H -#define SHELL_H - -#include "core/typedefs.h" -#include "core/ustring.h" - -/** - @author Juan Linietsky <reduzio@gmail.com> -*/ -class Shell { - - static Shell *singleton; - -public: - static Shell *get_singleton(); - virtual void execute(String p_path) = 0; - - Shell(); - virtual ~Shell(); -}; - -#endif diff --git a/core/pair.h b/core/pair.h index cb661160b5..9afaa726cb 100644 --- a/core/pair.h +++ b/core/pair.h @@ -37,7 +37,11 @@ struct Pair { F first; S second; - Pair() {} + Pair() : + first(), + second() { + } + Pair(F p_first, const S &p_second) : first(p_first), second(p_second) { diff --git a/core/dvector.cpp b/core/pool_vector.cpp index 592c3c053d..b9d2316315 100644 --- a/core/dvector.cpp +++ b/core/pool_vector.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* dvector.cpp */ +/* pool_vector.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,9 +28,9 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "dvector.h" +#include "pool_vector.h" -Mutex *dvector_lock = NULL; +Mutex *pool_vector_lock = NULL; PoolAllocator *MemoryPool::memory_pool = NULL; uint8_t *MemoryPool::pool_memory = NULL; diff --git a/core/dvector.h b/core/pool_vector.h index fc962b4940..102a620f17 100644 --- a/core/dvector.h +++ b/core/pool_vector.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* dvector.h */ +/* pool_vector.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef DVECTOR_H -#define DVECTOR_H +#ifndef POOL_VECTOR_H +#define POOL_VECTOR_H #include "core/os/copymem.h" #include "core/os/memory.h" @@ -188,19 +188,19 @@ class PoolVector { } } - void _reference(const PoolVector &p_dvector) { + void _reference(const PoolVector &p_pool_vector) { - if (alloc == p_dvector.alloc) + if (alloc == p_pool_vector.alloc) return; _unreference(); - if (!p_dvector.alloc) { + if (!p_pool_vector.alloc) { return; } - if (p_dvector.alloc->refcount.ref()) { - alloc = p_dvector.alloc; + if (p_pool_vector.alloc->refcount.ref()) { + alloc = p_pool_vector.alloc; } } @@ -460,11 +460,11 @@ public: void invert(); - void operator=(const PoolVector &p_dvector) { _reference(p_dvector); } + void operator=(const PoolVector &p_pool_vector) { _reference(p_pool_vector); } PoolVector() { alloc = NULL; } - PoolVector(const PoolVector &p_dvector) { + PoolVector(const PoolVector &p_pool_vector) { alloc = NULL; - _reference(p_dvector); + _reference(p_pool_vector); } ~PoolVector() { _unreference(); } }; @@ -640,4 +640,4 @@ void PoolVector<T>::invert() { } } -#endif +#endif // POOL_VECTOR_H diff --git a/core/project_settings.cpp b/core/project_settings.cpp index 8d05d7cc74..6b4895d688 100644 --- a/core/project_settings.cpp +++ b/core/project_settings.cpp @@ -501,7 +501,7 @@ Error ProjectSettings::_load_settings_binary(const String p_path) { d.resize(vlen); f->get_buffer(d.ptrw(), vlen); Variant value; - Error err = decode_variant(value, d.ptr(), d.size()); + err = decode_variant(value, d.ptr(), d.size()); ERR_EXPLAIN("Error decoding property: " + key); ERR_CONTINUE(err != OK); set(key, value); @@ -656,7 +656,7 @@ Error ProjectSettings::_save_settings_binary(const String &p_file, const Map<Str file->store_string(key); int len; - Error err = encode_variant(p_custom_features, NULL, len); + err = encode_variant(p_custom_features, NULL, len); if (err != OK) { memdelete(file); ERR_FAIL_V(err); @@ -694,7 +694,7 @@ Error ProjectSettings::_save_settings_binary(const String &p_file, const Map<Str file->store_string(key); int len; - Error err = encode_variant(value, NULL, len); + err = encode_variant(value, NULL, len); if (err != OK) memdelete(file); ERR_FAIL_COND_V(err != OK, ERR_INVALID_DATA); diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp index 60c2778603..97c96b4018 100644 --- a/core/register_core_types.cpp +++ b/core/register_core_types.cpp @@ -47,7 +47,7 @@ #include "core/io/packet_peer_udp.h" #include "core/io/pck_packer.h" #include "core/io/resource_format_binary.h" -#include "core/io/resource_import.h" +#include "core/io/resource_importer.h" #include "core/io/stream_peer_ssl.h" #include "core/io/tcp_server.h" #include "core/io/translation_loader_po.h" diff --git a/core/script_language.cpp b/core/script_language.cpp index 632fa3b336..f0310ffc31 100644 --- a/core/script_language.cpp +++ b/core/script_language.cpp @@ -37,6 +37,7 @@ int ScriptServer::_language_count = 0; bool ScriptServer::scripting_enabled = true; bool ScriptServer::reload_scripts_on_save = false; +bool ScriptServer::languages_finished = false; ScriptEditRequestFunction ScriptServer::edit_request_func = NULL; void Script::_notification(int p_what) { @@ -130,6 +131,7 @@ void ScriptServer::finish_languages() { _languages[i]->finish(); } global_classes_clear(); + languages_finished = true; } void ScriptServer::set_reload_scripts_on_save(bool p_enable) { @@ -525,8 +527,8 @@ void PlaceHolderScriptInstance::property_set_fallback(const StringName &p_name, } bool found = false; - for (const List<PropertyInfo>::Element *E = properties.front(); E; E = E->next()) { - if (E->get().name == p_name) { + for (const List<PropertyInfo>::Element *F = properties.front(); F; F = F->next()) { + if (F->get().name == p_name) { found = true; break; } diff --git a/core/script_language.h b/core/script_language.h index b0f12dc291..2d35097692 100644 --- a/core/script_language.h +++ b/core/script_language.h @@ -54,6 +54,7 @@ class ScriptServer { static int _language_count; static bool scripting_enabled; static bool reload_scripts_on_save; + static bool languages_finished; struct GlobalScriptClass { StringName language; @@ -91,6 +92,8 @@ public: static void init_languages(); static void finish_languages(); + + static bool are_languages_finished() { return languages_finished; } }; class ScriptInstance; diff --git a/core/sort.h b/core/sort_array.h index 4da7c323c7..0f258aec3e 100644 --- a/core/sort.h +++ b/core/sort_array.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* sort.h */ +/* sort_array.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef SORT_H -#define SORT_H +#ifndef SORT_ARRAY_H +#define SORT_ARRAY_H #include "core/typedefs.h" @@ -327,4 +327,4 @@ public: } }; -#endif +#endif // SORT_ARRAY_H diff --git a/core/string_db.cpp b/core/string_name.cpp index c776c56023..10b71ad3ac 100644 --- a/core/string_db.cpp +++ b/core/string_name.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* string_db.cpp */ +/* string_name.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,7 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "string_db.h" +#include "string_name.h" #include "core/os/os.h" #include "core/print_string.h" diff --git a/core/string_db.h b/core/string_name.h index 06b24c28da..0984b0181f 100644 --- a/core/string_db.h +++ b/core/string_name.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* string_db.h */ +/* string_name.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef STRING_DB_H -#define STRING_DB_H +#ifndef STRING_NAME_H +#define STRING_NAME_H #include "core/os/mutex.h" #include "core/safe_refcount.h" @@ -169,4 +169,4 @@ public: StringName _scs_create(const char *p_chr); -#endif +#endif // STRING_NAME_H diff --git a/core/translation.cpp b/core/translation.cpp index a402df3eea..6921f1d9f1 100644 --- a/core/translation.cpp +++ b/core/translation.cpp @@ -1052,7 +1052,7 @@ StringName TranslationServer::translate(const StringName &p_message) const { if (fallback.length() >= 2) { const CharType *fptr = &fallback[0]; - bool near_match = false; + near_match = false; for (const Set<Ref<Translation> >::Element *E = translations.front(); E; E = E->next()) { const Ref<Translation> &t = E->get(); diff --git a/core/typedefs.h b/core/typedefs.h index 0005e5e6ee..e01e1c00b9 100644 --- a/core/typedefs.h +++ b/core/typedefs.h @@ -116,6 +116,8 @@ T *_nullptr() { #define ABS(m_v) (((m_v) < 0) ? (-(m_v)) : (m_v)) #endif +#define ABSDIFF(x, y) (((x) < (y)) ? ((y) - (x)) : ((x) - (y))) + #ifndef SGN #define SGN(m_v) (((m_v) < 0) ? (-1.0) : (+1.0)) #endif diff --git a/core/undo_redo.cpp b/core/undo_redo.cpp index 6bc882eaec..40ccd95758 100644 --- a/core/undo_redo.cpp +++ b/core/undo_redo.cpp @@ -63,43 +63,37 @@ void UndoRedo::create_action(const String &p_name, MergeMode p_mode) { _discard_redo(); // Check if the merge operation is valid - if (p_mode != MERGE_DISABLE && actions.size() && actions[actions.size() - 1].name == p_name && actions[actions.size() - 1].last_tick + 800 > ticks) { + if (p_mode == MERGE_ENDS && actions.size() && actions[actions.size() - 1].name == p_name && actions[actions.size() - 1].last_tick + 800 > ticks) { current_action = actions.size() - 2; - if (p_mode == MERGE_ENDS) { + // Clear all do ops from last action, and delete all object references + List<Operation>::Element *E = actions.write[current_action + 1].do_ops.front(); - // Clear all do ops from last action, and delete all object references - List<Operation>::Element *E = actions.write[current_action + 1].do_ops.front(); + while (E) { - while (E) { + if (E->get().type == Operation::TYPE_REFERENCE) { - if (E->get().type == Operation::TYPE_REFERENCE) { + Object *obj = ObjectDB::get_instance(E->get().object); - Object *obj = ObjectDB::get_instance(E->get().object); - - if (obj) - memdelete(obj); - } - - E = E->next(); - actions.write[current_action + 1].do_ops.pop_front(); + if (obj) + memdelete(obj); } + + E = E->next(); + actions.write[current_action + 1].do_ops.pop_front(); } actions.write[actions.size() - 1].last_tick = ticks; - - merge_mode = p_mode; - } else { Action new_action; new_action.name = p_name; new_action.last_tick = ticks; actions.push_back(new_action); - - merge_mode = MERGE_DISABLE; } + + merge_mode = p_mode; } action_level++; @@ -234,7 +228,9 @@ void UndoRedo::_pop_history_tail() { } actions.remove(0); - current_action--; + if (current_action >= 0) { + current_action--; + } } void UndoRedo::commit_action() { @@ -258,11 +254,8 @@ void UndoRedo::_process_operation_list(List<Operation>::Element *E) { Operation &op = E->get(); Object *obj = ObjectDB::get_instance(op.object); - if (!obj) { - //corruption - clear_history(); - ERR_FAIL_COND(!obj); - } + if (!obj) //may have been deleted and this is fine + continue; switch (op.type) { diff --git a/core/ustring.cpp b/core/ustring.cpp index c1888c87a7..ff8fcaaaaf 100644 --- a/core/ustring.cpp +++ b/core/ustring.cpp @@ -603,13 +603,13 @@ String String::camelcase_to_underscore(bool lowercase) const { is_next_number = cstr[i + 1] >= '0' && cstr[i + 1] <= '9'; } - const bool a = is_upper && !was_precedent_upper && !was_precedent_number; - const bool b = was_precedent_upper && is_upper && are_next_2_lower; - const bool c = is_number && !was_precedent_number; + const bool cond_a = is_upper && !was_precedent_upper && !was_precedent_number; + const bool cond_b = was_precedent_upper && is_upper && are_next_2_lower; + const bool cond_c = is_number && !was_precedent_number; const bool can_break_number_letter = is_number && !was_precedent_number && is_next_lower; const bool can_break_letter_number = !is_number && was_precedent_number && (is_next_lower || is_next_number); - bool should_split = a || b || c || can_break_number_letter || can_break_letter_number; + bool should_split = cond_a || cond_b || cond_c || can_break_number_letter || can_break_letter_number; if (should_split) { new_string += this->substr(start_index, i - start_index) + "_"; start_index = i; @@ -1359,6 +1359,9 @@ bool String::parse_utf8(const char *p_utf8, int p_len) { #define _UNICERROR(m_err) print_line("Unicode error: " + String(m_err)); + if (!p_utf8) + return true; + String aux; int cstr_size = 0; @@ -2393,7 +2396,7 @@ int String::find(const char *p_str, int p_from) const { return -1; } -int String::find_char(CharType p_char, int p_from) const { +int String::find_char(const CharType &p_char, int p_from) const { return _cowdata.find(p_char, p_from); } @@ -2945,12 +2948,12 @@ String String::left(int p_pos) const { String String::right(int p_pos) const { - if (p_pos >= size()) - return *this; - - if (p_pos < 0) + if (p_pos >= length()) return ""; + if (p_pos <= 0) + return *this; + return substr(p_pos, (length() - p_pos)); } diff --git a/core/ustring.h b/core/ustring.h index 5ec5c79e2d..cb3d87378a 100644 --- a/core/ustring.h +++ b/core/ustring.h @@ -85,8 +85,7 @@ public: _FORCE_INLINE_ int size() const { return _cowdata.size(); } Error resize(int p_size) { return _cowdata.resize(p_size); } - _FORCE_INLINE_ char get(int p_index) { return _cowdata.get(p_index); } - _FORCE_INLINE_ const char get(int p_index) const { return _cowdata.get(p_index); } + _FORCE_INLINE_ char get(int p_index) const { return _cowdata.get(p_index); } _FORCE_INLINE_ void set(int p_index, const char &p_elem) { _cowdata.set(p_index, p_elem); } _FORCE_INLINE_ const char &operator[](int p_index) const { if (unlikely(p_index == _cowdata.size())) @@ -143,8 +142,7 @@ public: _FORCE_INLINE_ void clear() { resize(0); } - _FORCE_INLINE_ CharType get(int p_index) { return _cowdata.get(p_index); } - _FORCE_INLINE_ const CharType get(int p_index) const { return _cowdata.get(p_index); } + _FORCE_INLINE_ CharType get(int p_index) const { return _cowdata.get(p_index); } _FORCE_INLINE_ void set(int p_index, const CharType &p_elem) { _cowdata.set(p_index, p_elem); } _FORCE_INLINE_ int size() const { return _cowdata.size(); } Error resize(int p_size) { return _cowdata.resize(p_size); } @@ -197,7 +195,7 @@ public: String substr(int p_from, int p_chars) const; int find(const String &p_str, int p_from = 0) const; ///< return <0 if failed int find(const char *p_str, int p_from = 0) const; ///< return <0 if failed - int find_char(CharType p_char, int p_from = 0) const; ///< return <0 if failed + int find_char(const CharType &p_char, int p_from = 0) const; ///< return <0 if failed int find_last(const String &p_str) const; ///< return <0 if failed int findn(const String &p_str, int p_from = 0) const; ///< return <0 if failed, case insensitive int rfind(const String &p_str, int p_from = -1) const; ///< return <0 if failed diff --git a/core/variant.cpp b/core/variant.cpp index 56b272cccf..2ee2e8e293 100644 --- a/core/variant.cpp +++ b/core/variant.cpp @@ -2816,27 +2816,37 @@ uint32_t Variant::hash() const { const PoolVector<uint8_t> &arr = *reinterpret_cast<const PoolVector<uint8_t> *>(_data._mem); int len = arr.size(); - PoolVector<uint8_t>::Read r = arr.read(); - - return hash_djb2_buffer((uint8_t *)&r[0], len); + if (likely(len)) { + PoolVector<uint8_t>::Read r = arr.read(); + return hash_djb2_buffer((uint8_t *)&r[0], len); + } else { + return hash_djb2_one_64(0); + } } break; case POOL_INT_ARRAY: { const PoolVector<int> &arr = *reinterpret_cast<const PoolVector<int> *>(_data._mem); int len = arr.size(); - PoolVector<int>::Read r = arr.read(); - - return hash_djb2_buffer((uint8_t *)&r[0], len * sizeof(int)); + if (likely(len)) { + PoolVector<int>::Read r = arr.read(); + return hash_djb2_buffer((uint8_t *)&r[0], len * sizeof(int)); + } else { + return hash_djb2_one_64(0); + } } break; case POOL_REAL_ARRAY: { const PoolVector<real_t> &arr = *reinterpret_cast<const PoolVector<real_t> *>(_data._mem); int len = arr.size(); - PoolVector<real_t>::Read r = arr.read(); - return hash_djb2_buffer((uint8_t *)&r[0], len * sizeof(real_t)); + if (likely(len)) { + PoolVector<real_t>::Read r = arr.read(); + return hash_djb2_buffer((uint8_t *)&r[0], len * sizeof(real_t)); + } else { + return hash_djb2_one_float(0.0); + } } break; case POOL_STRING_ARRAY: { @@ -2844,10 +2854,13 @@ uint32_t Variant::hash() const { uint32_t hash = 5831; const PoolVector<String> &arr = *reinterpret_cast<const PoolVector<String> *>(_data._mem); int len = arr.size(); - PoolVector<String>::Read r = arr.read(); - for (int i = 0; i < len; i++) { - hash = hash_djb2_one_32(r[i].hash(), hash); + if (likely(len)) { + PoolVector<String>::Read r = arr.read(); + + for (int i = 0; i < len; i++) { + hash = hash_djb2_one_32(r[i].hash(), hash); + } } return hash; @@ -2857,48 +2870,54 @@ uint32_t Variant::hash() const { uint32_t hash = 5831; const PoolVector<Vector2> &arr = *reinterpret_cast<const PoolVector<Vector2> *>(_data._mem); int len = arr.size(); - PoolVector<Vector2>::Read r = arr.read(); - for (int i = 0; i < len; i++) { - hash = hash_djb2_one_float(r[i].x, hash); - hash = hash_djb2_one_float(r[i].y, hash); + if (likely(len)) { + PoolVector<Vector2>::Read r = arr.read(); + + for (int i = 0; i < len; i++) { + hash = hash_djb2_one_float(r[i].x, hash); + hash = hash_djb2_one_float(r[i].y, hash); + } } return hash; - } break; case POOL_VECTOR3_ARRAY: { uint32_t hash = 5831; const PoolVector<Vector3> &arr = *reinterpret_cast<const PoolVector<Vector3> *>(_data._mem); int len = arr.size(); - PoolVector<Vector3>::Read r = arr.read(); - for (int i = 0; i < len; i++) { - hash = hash_djb2_one_float(r[i].x, hash); - hash = hash_djb2_one_float(r[i].y, hash); - hash = hash_djb2_one_float(r[i].z, hash); + if (likely(len)) { + PoolVector<Vector3>::Read r = arr.read(); + + for (int i = 0; i < len; i++) { + hash = hash_djb2_one_float(r[i].x, hash); + hash = hash_djb2_one_float(r[i].y, hash); + hash = hash_djb2_one_float(r[i].z, hash); + } } return hash; - } break; case POOL_COLOR_ARRAY: { uint32_t hash = 5831; const PoolVector<Color> &arr = *reinterpret_cast<const PoolVector<Color> *>(_data._mem); int len = arr.size(); - PoolVector<Color>::Read r = arr.read(); - for (int i = 0; i < len; i++) { - hash = hash_djb2_one_float(r[i].r, hash); - hash = hash_djb2_one_float(r[i].g, hash); - hash = hash_djb2_one_float(r[i].b, hash); - hash = hash_djb2_one_float(r[i].a, hash); + if (likely(len)) { + PoolVector<Color>::Read r = arr.read(); + + for (int i = 0; i < len; i++) { + hash = hash_djb2_one_float(r[i].r, hash); + hash = hash_djb2_one_float(r[i].g, hash); + hash = hash_djb2_one_float(r[i].b, hash); + hash = hash_djb2_one_float(r[i].a, hash); + } } return hash; - } break; default: {} } diff --git a/core/variant.h b/core/variant.h index 0377c78ea8..9215d15bf0 100644 --- a/core/variant.h +++ b/core/variant.h @@ -38,17 +38,17 @@ #include "core/array.h" #include "core/color.h" #include "core/dictionary.h" -#include "core/dvector.h" #include "core/io/ip_address.h" #include "core/math/aabb.h" +#include "core/math/basis.h" #include "core/math/face3.h" -#include "core/math/matrix3.h" #include "core/math/plane.h" #include "core/math/quat.h" #include "core/math/transform.h" #include "core/math/transform_2d.h" #include "core/math/vector3.h" #include "core/node_path.h" +#include "core/pool_vector.h" #include "core/ref_ptr.h" #include "core/rid.h" #include "core/ustring.h" @@ -69,6 +69,13 @@ typedef PoolVector<Vector2> PoolVector2Array; typedef PoolVector<Vector3> PoolVector3Array; typedef PoolVector<Color> PoolColorArray; +// Temporary workaround until c++11 alignas() +#ifdef __GNUC__ +#define GCC_ALIGNED_8 __attribute__((aligned(8))) +#else +#define GCC_ALIGNED_8 +#endif + class Variant { public: // If this changes the table in variant_op must be updated @@ -132,7 +139,6 @@ private: _FORCE_INLINE_ const ObjData &_get_obj() const; union { - bool _bool; int64_t _int; double _real; @@ -142,7 +148,7 @@ private: Transform *_transform; void *_ptr; //generic pointer uint8_t _mem[sizeof(ObjData) > (sizeof(real_t) * 4) ? sizeof(ObjData) : (sizeof(real_t) * 4)]; - } _data; + } _data GCC_ALIGNED_8; void reference(const Variant &p_variant); void clear(); diff --git a/core/variant_call.cpp b/core/variant_call.cpp index f6f4569dfa..25a0f3957c 100644 --- a/core/variant_call.cpp +++ b/core/variant_call.cpp @@ -480,7 +480,7 @@ struct _VariantCall { VCALL_LOCALMEM0(Dictionary, clear); VCALL_LOCALMEM1R(Dictionary, has); VCALL_LOCALMEM1R(Dictionary, has_all); - VCALL_LOCALMEM1(Dictionary, erase); + VCALL_LOCALMEM1R(Dictionary, erase); VCALL_LOCALMEM0R(Dictionary, hash); VCALL_LOCALMEM0R(Dictionary, keys); VCALL_LOCALMEM0R(Dictionary, values); @@ -1227,15 +1227,15 @@ bool Variant::has_method(const StringName &p_method) const { #endif } - const _VariantCall::TypeFunc &fd = _VariantCall::type_funcs[type]; - return fd.functions.has(p_method); + const _VariantCall::TypeFunc &tf = _VariantCall::type_funcs[type]; + return tf.functions.has(p_method); } Vector<Variant::Type> Variant::get_method_argument_types(Variant::Type p_type, const StringName &p_method) { - const _VariantCall::TypeFunc &fd = _VariantCall::type_funcs[p_type]; + const _VariantCall::TypeFunc &tf = _VariantCall::type_funcs[p_type]; - const Map<StringName, _VariantCall::FuncData>::Element *E = fd.functions.find(p_method); + const Map<StringName, _VariantCall::FuncData>::Element *E = tf.functions.find(p_method); if (!E) return Vector<Variant::Type>(); @@ -1244,9 +1244,9 @@ Vector<Variant::Type> Variant::get_method_argument_types(Variant::Type p_type, c bool Variant::is_method_const(Variant::Type p_type, const StringName &p_method) { - const _VariantCall::TypeFunc &fd = _VariantCall::type_funcs[p_type]; + const _VariantCall::TypeFunc &tf = _VariantCall::type_funcs[p_type]; - const Map<StringName, _VariantCall::FuncData>::Element *E = fd.functions.find(p_method); + const Map<StringName, _VariantCall::FuncData>::Element *E = tf.functions.find(p_method); if (!E) return false; @@ -1255,9 +1255,9 @@ bool Variant::is_method_const(Variant::Type p_type, const StringName &p_method) Vector<StringName> Variant::get_method_argument_names(Variant::Type p_type, const StringName &p_method) { - const _VariantCall::TypeFunc &fd = _VariantCall::type_funcs[p_type]; + const _VariantCall::TypeFunc &tf = _VariantCall::type_funcs[p_type]; - const Map<StringName, _VariantCall::FuncData>::Element *E = fd.functions.find(p_method); + const Map<StringName, _VariantCall::FuncData>::Element *E = tf.functions.find(p_method); if (!E) return Vector<StringName>(); @@ -1266,9 +1266,9 @@ Vector<StringName> Variant::get_method_argument_names(Variant::Type p_type, cons Variant::Type Variant::get_method_return_type(Variant::Type p_type, const StringName &p_method, bool *r_has_return) { - const _VariantCall::TypeFunc &fd = _VariantCall::type_funcs[p_type]; + const _VariantCall::TypeFunc &tf = _VariantCall::type_funcs[p_type]; - const Map<StringName, _VariantCall::FuncData>::Element *E = fd.functions.find(p_method); + const Map<StringName, _VariantCall::FuncData>::Element *E = tf.functions.find(p_method); if (!E) return Variant::NIL; @@ -1280,9 +1280,9 @@ Variant::Type Variant::get_method_return_type(Variant::Type p_type, const String Vector<Variant> Variant::get_method_default_arguments(Variant::Type p_type, const StringName &p_method) { - const _VariantCall::TypeFunc &fd = _VariantCall::type_funcs[p_type]; + const _VariantCall::TypeFunc &tf = _VariantCall::type_funcs[p_type]; - const Map<StringName, _VariantCall::FuncData>::Element *E = fd.functions.find(p_method); + const Map<StringName, _VariantCall::FuncData>::Element *E = tf.functions.find(p_method); if (!E) return Vector<Variant>(); @@ -1291,9 +1291,9 @@ Vector<Variant> Variant::get_method_default_arguments(Variant::Type p_type, cons void Variant::get_method_list(List<MethodInfo> *p_list) const { - const _VariantCall::TypeFunc &fd = _VariantCall::type_funcs[type]; + const _VariantCall::TypeFunc &tf = _VariantCall::type_funcs[type]; - for (const Map<StringName, _VariantCall::FuncData>::Element *E = fd.functions.front(); E; E = E->next()) { + for (const Map<StringName, _VariantCall::FuncData>::Element *E = tf.functions.front(); E; E = E->next()) { const _VariantCall::FuncData &fd = E->get(); @@ -1405,11 +1405,11 @@ Variant Variant::get_constant_value(Variant::Type p_type, const StringName &p_va Map<StringName, int>::Element *E = cd.value.find(p_value); if (!E) { - Map<StringName, Variant>::Element *E = cd.variant_value.find(p_value); - if (E) { + Map<StringName, Variant>::Element *F = cd.variant_value.find(p_value); + if (F) { if (r_valid) *r_valid = true; - return E->get(); + return F->get(); } else { return -1; } diff --git a/core/variant_construct_string.cpp b/core/variant_construct_string.cpp deleted file mode 100644 index 2cb7481634..0000000000 --- a/core/variant_construct_string.cpp +++ /dev/null @@ -1,438 +0,0 @@ -/*************************************************************************/ -/* variant_construct_string.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "variant.h" - -class VariantConstruct { - - enum TokenType { - TK_CURLY_BRACKET_OPEN, - TK_CURLY_BRACKET_CLOSE, - TK_BRACKET_OPEN, - TK_BRACKET_CLOSE, - TK_IDENTIFIER, - TK_STRING, - TK_NUMBER, - TK_COLON, - TK_COMMA, - TK_EOF, - TK_MAX - }; - - enum Expecting { - - EXPECT_OBJECT, - EXPECT_OBJECT_KEY, - EXPECT_COLON, - EXPECT_OBJECT_VALUE, - }; - - struct Token { - - TokenType type; - Variant value; - }; - - static const char *tk_name[TK_MAX]; - - static String _print_var(const Variant &p_var); - - static Error _get_token(const CharType *p_str, int &index, int p_len, Token &r_token, int &line, String &r_err_str); - static Error _parse_value(Variant &value, Token &token, const CharType *p_str, int &index, int p_len, int &line, String &r_err_str, Variant::ObjectConstruct *p_construct, void *p_ud); - static Error _parse_array(Array &array, const CharType *p_str, int &index, int p_len, int &line, String &r_err_str, Variant::ObjectConstruct *p_construct, void *p_ud); - static Error _parse_dict(Dictionary &dict, const CharType *p_str, int &index, int p_len, int &line, String &r_err_str, Variant::ObjectConstruct *p_construct, void *p_ud); - -public: - static Error parse(const String &p_string, Variant &r_ret, String &r_err_str, int &r_err_line, Variant::ObjectConstruct *p_construct, void *p_ud); -}; - -const char *VariantConstruct::tk_name[TK_MAX] = { - "'{'", - "'}'", - "'['", - "']'", - "identifier", - "string", - "number", - "':'", - "','", - "EOF", -}; - -Error VariantConstruct::_get_token(const CharType *p_str, int &index, int p_len, Token &r_token, int &line, String &r_err_str) { - - while (true) { - switch (p_str[index]) { - - case '\n': { - - line++; - index++; - break; - }; - case 0: { - r_token.type = TK_EOF; - return OK; - } break; - case '{': { - - r_token.type = TK_CURLY_BRACKET_OPEN; - index++; - return OK; - }; - case '}': { - - r_token.type = TK_CURLY_BRACKET_CLOSE; - index++; - return OK; - }; - case '[': { - - r_token.type = TK_BRACKET_OPEN; - index++; - return OK; - }; - case ']': { - - r_token.type = TK_BRACKET_CLOSE; - index++; - return OK; - }; - case ':': { - - r_token.type = TK_COLON; - index++; - return OK; - }; - case ',': { - - r_token.type = TK_COMMA; - index++; - return OK; - }; - case '"': { - - index++; - String str; - while (true) { - if (p_str[index] == 0) { - r_err_str = "Unterminated String"; - return ERR_PARSE_ERROR; - } else if (p_str[index] == '"') { - index++; - break; - } else if (p_str[index] == '\\') { - //escaped characters... - index++; - CharType next = p_str[index]; - if (next == 0) { - r_err_str = "Unterminated String"; - return ERR_PARSE_ERROR; - } - CharType res = 0; - - switch (next) { - - case 'b': res = 8; break; - case 't': res = 9; break; - case 'n': res = 10; break; - case 'f': res = 12; break; - case 'r': res = 13; break; - case '\"': res = '\"'; break; - case '\\': res = '\\'; break; - case '/': res = '/'; break; - case 'u': { - //hexnumbarh - oct is deprecated - - for (int j = 0; j < 4; j++) { - CharType c = p_str[index + j + 1]; - if (c == 0) { - r_err_str = "Unterminated String"; - return ERR_PARSE_ERROR; - } - if (!((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'))) { - - r_err_str = "Malformed hex constant in string"; - return ERR_PARSE_ERROR; - } - CharType v; - if (c >= '0' && c <= '9') { - v = c - '0'; - } else if (c >= 'a' && c <= 'f') { - v = c - 'a'; - v += 10; - } else if (c >= 'A' && c <= 'F') { - v = c - 'A'; - v += 10; - } else { - ERR_PRINT("BUG"); - v = 0; - } - - res <<= 4; - res |= v; - } - index += 4; //will add at the end anyway - - } break; - default: { - - r_err_str = "Invalid escape sequence"; - return ERR_PARSE_ERROR; - } break; - } - - str += res; - - } else { - if (p_str[index] == '\n') - line++; - str += p_str[index]; - } - index++; - } - - r_token.type = TK_STRING; - r_token.value = str; - return OK; - - } break; - default: { - - if (p_str[index] <= 32) { - index++; - break; - } - - if (p_str[index] == '-' || (p_str[index] >= '0' && p_str[index] <= '9')) { - //a number - const CharType *rptr; - double number = String::to_double(&p_str[index], &rptr); - index += (rptr - &p_str[index]); - r_token.type = TK_NUMBER; - r_token.value = number; - return OK; - - } else if ((p_str[index] >= 'A' && p_str[index] <= 'Z') || (p_str[index] >= 'a' && p_str[index] <= 'z')) { - - String id; - - while ((p_str[index] >= 'A' && p_str[index] <= 'Z') || (p_str[index] >= 'a' && p_str[index] <= 'z')) { - - id += p_str[index]; - index++; - } - - r_token.type = TK_IDENTIFIER; - r_token.value = id; - return OK; - } else { - r_err_str = "Unexpected character."; - return ERR_PARSE_ERROR; - } - } - } - } - - return ERR_PARSE_ERROR; -} - -Error VariantConstruct::_parse_value(Variant &value, Token &token, const CharType *p_str, int &index, int p_len, int &line, String &r_err_str, Variant::ObjectConstruct *p_construct, void *p_ud) { - - if (token.type == TK_CURLY_BRACKET_OPEN) { - - Dictionary d; - Error err = _parse_dict(d, p_str, index, p_len, line, r_err_str, p_construct, p_ud); - if (err) - return err; - value = d; - return OK; - } else if (token.type == TK_BRACKET_OPEN) { - - Array a; - Error err = _parse_array(a, p_str, index, p_len, line, r_err_str, p_construct, p_ud); - if (err) - return err; - value = a; - return OK; - - } else if (token.type == TK_IDENTIFIER) { - - String id = token.value; - if (id == "true") - value = true; - else if (id == "false") - value = false; - else if (id == "null") - value = Variant(); - else { - r_err_str = "Expected 'true','false' or 'null', got '" + id + "'."; - return ERR_PARSE_ERROR; - } - return OK; - - } else if (token.type == TK_NUMBER) { - - value = token.value; - return OK; - } else if (token.type == TK_STRING) { - - value = token.value; - return OK; - } else { - r_err_str = "Expected value, got " + String(tk_name[token.type]) + "."; - return ERR_PARSE_ERROR; - } - - return ERR_PARSE_ERROR; -} - -Error VariantConstruct::_parse_array(Array &array, const CharType *p_str, int &index, int p_len, int &line, String &r_err_str, Variant::ObjectConstruct *p_construct, void *p_ud) { - - Token token; - bool need_comma = false; - - while (index < p_len) { - - Error err = _get_token(p_str, index, p_len, token, line, r_err_str); - if (err != OK) - return err; - - if (token.type == TK_BRACKET_CLOSE) { - - return OK; - } - - if (need_comma) { - - if (token.type != TK_COMMA) { - - r_err_str = "Expected ','"; - return ERR_PARSE_ERROR; - } else { - need_comma = false; - continue; - } - } - - Variant v; - err = _parse_value(v, token, p_str, index, p_len, line, r_err_str, p_construct, p_ud); - if (err) - return err; - - array.push_back(v); - need_comma = true; - } - - return OK; -} - -Error VariantConstruct::_parse_dict(Dictionary &dict, const CharType *p_str, int &index, int p_len, int &line, String &r_err_str, Variant::ObjectConstruct *p_construct, void *p_ud) { - - bool at_key = true; - Variant key; - Token token; - bool need_comma = false; - - while (index < p_len) { - - if (at_key) { - - Error err = _get_token(p_str, index, p_len, token, line, r_err_str); - if (err != OK) - return err; - - if (token.type == TK_CURLY_BRACKET_CLOSE) { - - return OK; - } - - if (need_comma) { - - if (token.type != TK_COMMA) { - - r_err_str = "Expected '}' or ','"; - return ERR_PARSE_ERROR; - } else { - need_comma = false; - continue; - } - } - - err = _parse_value(key, token, p_str, index, p_len, line, r_err_str, p_construct, p_ud); - - if (err != OK) - return err; - - err = _get_token(p_str, index, p_len, token, line, r_err_str); - - if (err != OK) - return err; - - if (token.type != TK_COLON) { - - r_err_str = "Expected ':'"; - return ERR_PARSE_ERROR; - } - at_key = false; - } else { - - Error err = _get_token(p_str, index, p_len, token, line, r_err_str); - if (err != OK) - return err; - - Variant v; - err = _parse_value(v, token, p_str, index, p_len, line, r_err_str, p_construct, p_ud); - if (err) - return err; - dict[key] = v; - need_comma = true; - at_key = true; - } - } - - return OK; -} - -Error VariantConstruct::parse(const String &p_string, Variant &r_ret, String &r_err_str, int &r_err_line, Variant::ObjectConstruct *p_construct, void *p_ud) { - - const CharType *str = p_string.ptr(); - int idx = 0; - int len = p_string.length(); - Token token; - r_err_line = 0; - String aux_key; - - Error err = _get_token(str, idx, len, token, r_err_line, r_err_str); - if (err) - return err; - - return _parse_value(r_ret, token, str, idx, len, r_err_line, r_err_str, p_construct, p_ud); -} diff --git a/core/variant_op.cpp b/core/variant_op.cpp index 93654d3389..26851e4c23 100644 --- a/core/variant_op.cpp +++ b/core/variant_op.cpp @@ -3496,15 +3496,15 @@ void Variant::blend(const Variant &a, const Variant &b, float c, Variant &r_dst) case COLOR: { const Color *ca = reinterpret_cast<const Color *>(a._data._mem); const Color *cb = reinterpret_cast<const Color *>(b._data._mem); - float r = ca->r + cb->r * c; - float g = ca->g + cb->g * c; - float b = ca->b + cb->b * c; - float a = ca->a + cb->a * c; - r = r > 1.0 ? 1.0 : r; - g = g > 1.0 ? 1.0 : g; - b = b > 1.0 ? 1.0 : b; - a = a > 1.0 ? 1.0 : a; - r_dst = Color(r, g, b, a); + float new_r = ca->r + cb->r * c; + float new_g = ca->g + cb->g * c; + float new_b = ca->b + cb->b * c; + float new_a = ca->a + cb->a * c; + new_r = new_r > 1.0 ? 1.0 : new_r; + new_g = new_g > 1.0 ? 1.0 : new_g; + new_b = new_b > 1.0 ? 1.0 : new_b; + new_a = new_a > 1.0 ? 1.0 : new_a; + r_dst = Color(new_r, new_g, new_b, new_a); } return; default: { diff --git a/core/variant_parser.cpp b/core/variant_parser.cpp index 84fb85e812..0056fc75b6 100644 --- a/core/variant_parser.cpp +++ b/core/variant_parser.cpp @@ -728,7 +728,7 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, bool at_key = true; String key; - Token token; + Token token2; bool need_comma = false; while (true) { @@ -740,11 +740,11 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, if (at_key) { - Error err = get_token(p_stream, token, line, r_err_str); + Error err = get_token(p_stream, token2, line, r_err_str); if (err != OK) return err; - if (token.type == TK_PARENTHESIS_CLOSE) { + if (token2.type == TK_PARENTHESIS_CLOSE) { Reference *reference = Object::cast_to<Reference>(obj); if (reference) { value = REF(reference); @@ -756,7 +756,7 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, if (need_comma) { - if (token.type != TK_COMMA) { + if (token2.type != TK_COMMA) { r_err_str = "Expected '}' or ','"; return ERR_PARSE_ERROR; @@ -766,18 +766,18 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, } } - if (token.type != TK_STRING) { + if (token2.type != TK_STRING) { r_err_str = "Expected property name as string"; return ERR_PARSE_ERROR; } - key = token.value; + key = token2.value; - err = get_token(p_stream, token, line, r_err_str); + err = get_token(p_stream, token2, line, r_err_str); if (err != OK) return err; - if (token.type != TK_COLON) { + if (token2.type != TK_COLON) { r_err_str = "Expected ':'"; return ERR_PARSE_ERROR; @@ -785,12 +785,12 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, at_key = false; } else { - Error err = get_token(p_stream, token, line, r_err_str); + Error err = get_token(p_stream, token2, line, r_err_str); if (err != OK) return err; Variant v; - err = parse_value(token, v, p_stream, line, r_err_str, p_res_parser); + err = parse_value(token2, v, p_stream, line, r_err_str, p_res_parser); if (err) return err; obj->set(key, v); @@ -882,11 +882,11 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, return ERR_PARSE_ERROR; } - String id = token.value; + String id2 = token.value; Ref<InputEvent> ie; - if (id == "NONE") { + if (id2 == "NONE") { get_token(p_stream, token, line, r_err_str); @@ -895,7 +895,7 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, return ERR_PARSE_ERROR; } - } else if (id == "KEY") { + } else if (id2 == "KEY") { Ref<InputEventKey> key; key.instance(); @@ -954,7 +954,7 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, return ERR_PARSE_ERROR; } - } else if (id == "MBUTTON") { + } else if (id2 == "MBUTTON") { Ref<InputEventMouseButton> mb; mb.instance(); @@ -980,7 +980,7 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, return ERR_PARSE_ERROR; } - } else if (id == "JBUTTON") { + } else if (id2 == "JBUTTON") { Ref<InputEventJoypadButton> jb; jb.instance(); @@ -1006,7 +1006,7 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, return ERR_PARSE_ERROR; } - } else if (id == "JAXIS") { + } else if (id2 == "JAXIS") { Ref<InputEventJoypadMotion> jm; jm.instance(); @@ -1597,7 +1597,7 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str } break; case Variant::INT: { - p_store_string_func(p_store_string_ud, itos(p_variant.operator int())); + p_store_string_func(p_store_string_ud, itos(p_variant.operator int64_t())); } break; case Variant::REAL: { diff --git a/core/vector.h b/core/vector.h index 90b3d90826..93ee003519 100644 --- a/core/vector.h +++ b/core/vector.h @@ -40,7 +40,7 @@ #include "core/cowdata.h" #include "core/error_macros.h" #include "core/os/memory.h" -#include "core/sort.h" +#include "core/sort_array.h" template <class T> class VectorWriteProxy { diff --git a/core/version.h b/core/version.h index 46eecf6125..05fec9d0a6 100644 --- a/core/version.h +++ b/core/version.h @@ -41,9 +41,14 @@ #ifdef VERSION_PATCH // Example: "3.1.4" #define VERSION_NUMBER "" VERSION_BRANCH "." _MKSTR(VERSION_PATCH) +// Version number encoded as hexadecimal int with one byte for each number, +// for easy comparison from code. +// Example: 3.1.4 will be 0x030104, making comparison easy from script. +#define VERSION_HEX 0x10000 * VERSION_MAJOR + 0x100 * VERSION_MINOR + VERSION_PATCH #else // Example: "3.1" #define VERSION_NUMBER "" VERSION_BRANCH +#define VERSION_HEX 0x10000 * VERSION_MAJOR + 0x100 * VERSION_MINOR #endif // VERSION_PATCH // Describes the full configuration of that Godot version, including the version number, diff --git a/doc/classes/@GDScript.xml b/doc/classes/@GDScript.xml index 072eec800f..7b4b3e43ba 100644 --- a/doc/classes/@GDScript.xml +++ b/doc/classes/@GDScript.xml @@ -811,7 +811,7 @@ <description> Random range, any floating point value between [code]from[/code] and [code]to[/code]. [codeblock] - prints(rand_range(0, 1), rand_range(0, 1)) # prints 0.135591 0.405263 + prints(rand_range(0, 1), rand_range(0, 1)) # prints e.g. 0.135591 0.405263 [/codeblock] </description> </method> @@ -828,9 +828,9 @@ <return type="float"> </return> <description> - Returns a random floating point value between 0 and 1. + Returns a random floating point value on the interval [code][0, 1][/code]. [codeblock] - randf() # returns 0.375671 + randf() # returns e.g. 0.375671 [/codeblock] </description> </method> @@ -838,11 +838,12 @@ <return type="int"> </return> <description> - Returns a random 32 bit integer. Use remainder to obtain a random value between 0 and N (where N is smaller than 2^32 -1). + Returns a random unsigned 32 bit integer. Use remainder to obtain a random value in the interval [code][0, N][/code] (where N is smaller than 2^32 -1). [codeblock] - randi() % 20 # returns random number between 0 and 19 - randi() % 100 # returns random number between 0 and 99 - randi() % 100 + 1 # returns random number between 1 and 100 + randi() # returns random integer between 0 and 2^32 - 1 + randi() % 20 # returns random integer between 0 and 19 + randi() % 100 # returns random integer between 0 and 99 + randi() % 100 + 1 # returns random integer between 1 and 100 [/codeblock] </description> </method> diff --git a/doc/classes/Animation.xml b/doc/classes/Animation.xml index a7cae709a4..eaaa64d53d 100644 --- a/doc/classes/Animation.xml +++ b/doc/classes/Animation.xml @@ -648,6 +648,12 @@ The animation step value. </member> </members> + <signals> + <signal name="tracks_changed"> + <description> + </description> + </signal> + </signals> <constants> <constant name="TYPE_VALUE" value="0" enum="TrackType"> Value tracks set values in node properties, but only those which can be Interpolated. diff --git a/doc/classes/AnimationPlayer.xml b/doc/classes/AnimationPlayer.xml index 499da4b8a3..9d68102952 100644 --- a/doc/classes/AnimationPlayer.xml +++ b/doc/classes/AnimationPlayer.xml @@ -145,6 +145,7 @@ </argument> <description> Play the animation with key [code]name[/code]. Custom speed and blend times can be set. If custom speed is negative (-1), 'from_end' being true can play the animation backwards. + If the animation has been paused by [code]stop(true)[/code] it will be resumed. Calling [code]play()[/code] without arguments will also resume the animation. </description> </method> <method name="play_backwards"> @@ -156,6 +157,7 @@ </argument> <description> Play the animation with key [code]name[/code] in reverse. + If the animation has been paused by [code]stop(true)[/code] it will be resumed backwards. Calling [code]play_backwards()[/code] without arguments will also resume the animation backwards. </description> </method> <method name="queue"> @@ -217,7 +219,8 @@ <argument index="0" name="reset" type="bool" default="true"> </argument> <description> - Stop the currently playing animation. If [code]reset[/code] is [code]true[/code], the anim position is reset to [code]0[/code]. + Stop the currently playing animation. If [code]reset[/code] is [code]true[/code], the animation position is reset to [code]0[/code] and the playback speed is reset to [code]1.0[/code]. + If [code]reset[/code] is [code]false[/code], then calling [code]play()[/code] without arguments or [code]play("same_as_before")[/code] will resume the animation. Works the same for the [code]play_backwards()[/code] method. </description> </method> </methods> diff --git a/doc/classes/AudioBusLayout.xml b/doc/classes/AudioBusLayout.xml index c43da3e233..f122906167 100644 --- a/doc/classes/AudioBusLayout.xml +++ b/doc/classes/AudioBusLayout.xml @@ -4,7 +4,7 @@ Stores information about the audiobusses. </brief_description> <description> - Stores position, muting, solo, bypass, effects, effect position, volume, and the connections between busses. See [AudioServer] for usage. + Stores position, muting, solo, bypass, effects, effect position, volume, and the connections between buses. See [AudioServer] for usage. </description> <tutorials> </tutorials> diff --git a/doc/classes/AudioEffectLimiter.xml b/doc/classes/AudioEffectLimiter.xml index 9e791f02d7..5c5c55d17b 100644 --- a/doc/classes/AudioEffectLimiter.xml +++ b/doc/classes/AudioEffectLimiter.xml @@ -4,7 +4,7 @@ Adds a soft clip Limiter audio effect to an Audio bus. </brief_description> <description> - A limiter is similar to a compressor, but it’s less flexible and designed to disallow sound going over a given dB threshold. Adding one in the Master Bus is always recommended to reduce the effects of clipping. + A limiter is similar to a compressor, but it's less flexible and designed to disallow sound going over a given dB threshold. Adding one in the Master Bus is always recommended to reduce the effects of clipping. Soft clipping starts to reduce the peaks a little below the threshold level and progressively increases its effect as the input level increases such that the threshold is never exceeded. </description> <tutorials> diff --git a/doc/classes/AudioServer.xml b/doc/classes/AudioServer.xml index 96f02137cf..eb3c7cb3b4 100644 --- a/doc/classes/AudioServer.xml +++ b/doc/classes/AudioServer.xml @@ -58,7 +58,7 @@ <return type="AudioBusLayout"> </return> <description> - Generates an [AudioBusLayout] using the available busses and effects. + Generates an [AudioBusLayout] using the available buses and effects. </description> </method> <method name="get_bus_channels" qualifiers="const"> @@ -74,7 +74,7 @@ <return type="int"> </return> <description> - Returns the number of available busses. + Returns the number of available buses. </description> </method> <method name="get_bus_effect"> @@ -274,7 +274,7 @@ <argument index="0" name="amount" type="int"> </argument> <description> - Adds and removes busses to make the number of busses match [code]amount[/code]. + Adds and removes buses to make the number of buses match [code]amount[/code]. </description> </method> <method name="set_bus_effect_enabled"> diff --git a/doc/classes/Camera.xml b/doc/classes/Camera.xml index f4b1bc1519..e56fb63dc5 100644 --- a/doc/classes/Camera.xml +++ b/doc/classes/Camera.xml @@ -35,6 +35,12 @@ <description> </description> </method> + <method name="get_frustum" qualifiers="const"> + <return type="Array"> + </return> + <description> + </description> + </method> <method name="is_position_behind" qualifiers="const"> <return type="bool"> </return> diff --git a/doc/classes/CollisionPolygon.xml b/doc/classes/CollisionPolygon.xml index 28e9ba4217..0b4f07578e 100644 --- a/doc/classes/CollisionPolygon.xml +++ b/doc/classes/CollisionPolygon.xml @@ -20,7 +20,7 @@ If true, no collision will be produced. </member> <member name="polygon" type="PoolVector2Array" setter="set_polygon" getter="get_polygon"> - Array of vertices which define the polygon. + Array of vertices which define the polygon. Note that the returned value is a copy of the original. Methods which mutate the size or properties of the return value will not impact the original polygon. To change properties of the polygon, assign it to a temporary variable and make changes before reassigning the [code]polygon[/code] member. </member> </members> <constants> diff --git a/doc/classes/CollisionPolygon2D.xml b/doc/classes/CollisionPolygon2D.xml index 3dd87a4120..e754a2f2d1 100644 --- a/doc/classes/CollisionPolygon2D.xml +++ b/doc/classes/CollisionPolygon2D.xml @@ -25,7 +25,7 @@ <member name="one_way_collision_margin" type="float" setter="set_one_way_collision_margin" getter="get_one_way_collision_margin"> </member> <member name="polygon" type="PoolVector2Array" setter="set_polygon" getter="get_polygon"> - The polygon's list of vertices. The final point will be connected to the first. + The polygon's list of vertices. The final point will be connected to the first. The returned value is a clone of the PoolVector2Array, not a reference. </member> </members> <constants> diff --git a/doc/classes/Control.xml b/doc/classes/Control.xml index d27839e0a6..0152cca957 100644 --- a/doc/classes/Control.xml +++ b/doc/classes/Control.xml @@ -9,7 +9,7 @@ [b]User Interface nodes and input[/b] Godot sends input events to the scene's root node first, by calling [method Node._input]. [method Node._input] forwards the event down the node tree to the nodes under the mouse cursor, or on keyboard focus. To do so, it calls [method MainLoop._input_event]. Call [method accept_event] so no other node receives the event. Once you accepted an input, it becomes handled so [method Node._unhandled_input] will not process it. Only one [code]Control[/code] node can be in keyboard focus. Only the node in focus will receive keyboard events. To get the focus, call [method grab_focus]. [code]Control[/code] nodes lose focus when another node grabs it, or if you hide the node in focus. - Set [member mouse_filter] to MOUSE_FILTER_IGNORE to tell a [code]Control[/code] node to ignore mouse or touch events. You'll need it if you place an icon on top of a button. + Set [member mouse_filter] to [constant MOUSE_FILTER_IGNORE] to tell a [code]Control[/code] node to ignore mouse or touch events. You'll need it if you place an icon on top of a button. [Theme] resources change the Control's appearance. If you change the [Theme] on a [code]Control[/code] node, it affects all of its children. To override some of the theme's parameters, call one of the [code]add_*_override[/code] methods, like [method add_font_override]. You can override the theme with the inspector. </description> <tutorials> @@ -658,7 +658,7 @@ Controls the direction on the vertical axis in which the control should grow if its vertical minimum size is changed to be greater than its current size, as the control always has to be at least the minimum size. </member> <member name="hint_tooltip" type="String" setter="set_tooltip" getter="_get_tooltip"> - Changes the tooltip text. The tooltip appears when the user's mouse cursor stays idle over this control for a few moments. + Changes the tooltip text. The tooltip appears when the user's mouse cursor stays idle over this control for a few moments, provided that the [member mouse_filter] property is not [constant MOUSE_FILTER_IGNORE]. </member> <member name="margin_bottom" type="float" setter="set_margin" getter="get_margin"> Distance between the node's bottom edge and its parent control, based on [member anchor_bottom]. @@ -941,10 +941,10 @@ The control will grow to the left or top to make up if its minimum size is changed to be greater than its current size on the respective axis. </constant> <constant name="GROW_DIRECTION_END" value="1" enum="GrowDirection"> - The control wil grow to the right or bottom to make up if its minimum size is changed to be greater than its current size on the respective axis. + The control will grow to the right or bottom to make up if its minimum size is changed to be greater than its current size on the respective axis. </constant> <constant name="GROW_DIRECTION_BOTH" value="2" enum="GrowDirection"> - The control wil grow in both directions equally to make up if its minimum size is changed to be greater than its current size. + The control will grow in both directions equally to make up if its minimum size is changed to be greater than its current size. </constant> <constant name="ANCHOR_BEGIN" value="0" enum="Anchor"> Snaps one of the 4 anchor's sides to the origin of the node's [code]Rect[/code], in the top left. Use it with one of the [code]anchor_*[/code] member variables, like [member anchor_left]. To change all 4 anchors at once, use [method set_anchors_preset]. diff --git a/doc/classes/Dictionary.xml b/doc/classes/Dictionary.xml index a9e2a38dcf..9c78853cfe 100644 --- a/doc/classes/Dictionary.xml +++ b/doc/classes/Dictionary.xml @@ -5,6 +5,7 @@ </brief_description> <description> Dictionary type. Associative container which contains values referenced by unique keys. Dictionaries are always passed by reference. + Erasing elements while iterating over them [b]is not supported[/b]. </description> <tutorials> </tutorials> @@ -38,7 +39,7 @@ <argument index="0" name="key" type="Variant"> </argument> <description> - Erase a dictionary key/value pair by key. + Erase a dictionary key/value pair by key. Do not erase elements while iterating over the dictionary. </description> </method> <method name="get"> diff --git a/doc/classes/EditorSpatialGizmoPlugin.xml b/doc/classes/EditorSpatialGizmoPlugin.xml index a62b23ead8..a6c0413c19 100644 --- a/doc/classes/EditorSpatialGizmoPlugin.xml +++ b/doc/classes/EditorSpatialGizmoPlugin.xml @@ -134,7 +134,7 @@ <return type="String"> </return> <description> - Override this method to provide the name that will appear in teh gizmo visibility menu. + Override this method to provide the name that will appear in the gizmo visibility menu. </description> </method> <method name="has_gizmo" qualifiers="virtual"> diff --git a/doc/classes/Engine.xml b/doc/classes/Engine.xml index f921b76b21..b8808b8b53 100644 --- a/doc/classes/Engine.xml +++ b/doc/classes/Engine.xml @@ -90,9 +90,17 @@ "major" - Holds the major version number as an int "minor" - Holds the minor version number as an int "patch" - Holds the patch version number as an int + "hex" - Holds the full version number encoded as an hexadecimal int with one byte (2 places) per number (see example below) "status" - Holds the status (e.g. "beta", "rc1", "rc2", ... "stable") as a String "build" - Holds the build name (e.g. "custom-build") as a String "string" - major + minor + patch + status + build in a single String + The "hex" value is encoded as follows, from left to right: one byte for the major, one byte for the minor, one byte for the patch version. For example, "3.1.12" would be [code]0x03010C[/code]. Note that it's still an int internally, and printing it will give you its decimal representation, which is not particularly meaningful. Use hexadecimal literals for easy version comparisons from code: + [codeblock] + if Engine.get_version_info().hex >= 0x030200: + # do things specific to version 3.2 or later + else: + # do things specific to versions before 3.2 + [/codeblock] </description> </method> <method name="has_singleton" qualifiers="const"> diff --git a/doc/classes/Expression.xml b/doc/classes/Expression.xml index b0a21d7f82..78623b359e 100644 --- a/doc/classes/Expression.xml +++ b/doc/classes/Expression.xml @@ -39,6 +39,7 @@ </argument> <description> Executes the expression that was previously parsed by [method parse] and returns the result. Before you use the returned object, you should check if the method failed by calling [method has_execute_failed]. + If you defined input variables in [method parse], you can specify their values in the inputs array, in the same order. </description> </method> <method name="get_error_text" qualifiers="const"> @@ -64,6 +65,7 @@ </argument> <description> Parses the expression and returns a [enum @GlobalScope.Error]. + You can optionally specify names of variables that may appear in the expression with [code]input_names[/code], so that you can bind them when it gets executed. </description> </method> </methods> diff --git a/doc/classes/File.xml b/doc/classes/File.xml index 6462176c73..c9a8f18116 100644 --- a/doc/classes/File.xml +++ b/doc/classes/File.xml @@ -38,7 +38,7 @@ <return type="bool"> </return> <description> - Returns [code]true[/code] if the file cursor has reached the end of the file. + Returns [code]true[/code] if the file cursor has read past the end of the file. Note that this function will still return [code]false[/code] while at the end of the file and only activates when reading past it. This can be confusing but it conforms to how low level file access works in all operating systems. There is always [method get_len] and [method get_position] to implement a custom logic. </description> </method> <method name="file_exists" qualifiers="const"> diff --git a/doc/classes/Image.xml b/doc/classes/Image.xml index 8868dd778d..f165027d44 100644 --- a/doc/classes/Image.xml +++ b/doc/classes/Image.xml @@ -227,7 +227,7 @@ <return type="int" enum="Image.Format"> </return> <description> - Returns the image’s format. See [code]FORMAT_*[/code] constants. + Returns the image's format. See [code]FORMAT_*[/code] constants. </description> </method> <method name="get_height" qualifiers="const"> diff --git a/doc/classes/Label.xml b/doc/classes/Label.xml index 90547b7c2f..36aa3c8b55 100644 --- a/doc/classes/Label.xml +++ b/doc/classes/Label.xml @@ -5,7 +5,7 @@ </brief_description> <description> Label displays plain text on the screen. It gives you control over the horizontal and vertical alignment, and can wrap the text inside the node's bounding rectangle. It doesn't support bold, italics or other formatting. For that, use [RichTextLabel] instead. - Note that contrarily to most other [Control]s, Label's [member Control.mouse_filter] defaults to MOUSE_FILTER_IGNORE (i.e. it doesn't react to mouse input events). + Note that contrarily to most other [Control]s, Label's [member Control.mouse_filter] defaults to MOUSE_FILTER_IGNORE (i.e. it doesn't react to mouse input events). This implies that a label won't display any configured [member Control.hint_tooltip], unless you change its mouse filter. </description> <tutorials> </tutorials> diff --git a/doc/classes/MultiMesh.xml b/doc/classes/MultiMesh.xml index 1908fdd684..565e19c229 100644 --- a/doc/classes/MultiMesh.xml +++ b/doc/classes/MultiMesh.xml @@ -4,8 +4,8 @@ Provides high performance mesh instancing. </brief_description> <description> - MultiMesh provides low level mesh instancing. If the amount of [Mesh] instances needed goes from hundreds to thousands (and most need to be visible at close proximity) creating such a large amount of [MeshInstance] nodes may affect performance by using too much CPU or video memory. - For this case a MultiMesh becomes very useful, as it can draw thousands of instances with little API overhead. + MultiMesh provides low level mesh instancing. Drawing thousands of [MeshInstance] nodes can be slow because each object is submitted to the GPU to be drawn individually. + MultiMesh is much faster because it can draw thousands of instances with a single draw call, resulting in less API overhead. As a drawback, if the instances are too far away of each other, performance may be reduced as every single instance will always rendered (they are spatially indexed as one, for the whole object). Since instances may have any behavior, the AABB used for visibility must be provided by the user. </description> @@ -36,6 +36,7 @@ <argument index="0" name="instance" type="int"> </argument> <description> + Return the custom data that has been set for a specific instance. </description> </method> <method name="get_instance_transform" qualifiers="const"> @@ -47,6 +48,14 @@ Return the transform of a specific instance. </description> </method> + <method name="get_instance_transform_2d" qualifiers="const"> + <return type="Transform2D"> + </return> + <argument index="0" name="instance" type="int"> + </argument> + <description> + </description> + </method> <method name="set_instance_color"> <return type="void"> </return> @@ -66,6 +75,7 @@ <argument index="1" name="custom_data" type="Color"> </argument> <description> + Set custom data for a specific instance. Although [Color] is used, it is just a container for 4 numbers. </description> </method> <method name="set_instance_transform"> @@ -79,35 +89,58 @@ Set the transform for a specific instance. </description> </method> + <method name="set_instance_transform_2d"> + <return type="void"> + </return> + <argument index="0" name="instance" type="int"> + </argument> + <argument index="1" name="transform" type="Transform2D"> + </argument> + <description> + </description> + </method> </methods> <members> <member name="color_format" type="int" setter="set_color_format" getter="get_color_format" enum="MultiMesh.ColorFormat"> + Format of colors in color array that gets passed to shader. </member> <member name="custom_data_format" type="int" setter="set_custom_data_format" getter="get_custom_data_format" enum="MultiMesh.CustomDataFormat"> + Format of custom data in custom data array that gets passed to shader. </member> <member name="instance_count" type="int" setter="set_instance_count" getter="get_instance_count"> + Number of instances that will get drawn. </member> <member name="mesh" type="Mesh" setter="set_mesh" getter="get_mesh"> + Mesh to be drawn. </member> <member name="transform_format" type="int" setter="set_transform_format" getter="get_transform_format" enum="MultiMesh.TransformFormat"> + Format of transform used to transform mesh, either 2D or 3D. </member> </members> <constants> <constant name="TRANSFORM_2D" value="0" enum="TransformFormat"> + Use this when using 2D transforms. </constant> <constant name="TRANSFORM_3D" value="1" enum="TransformFormat"> + Use this when using 3D transforms. </constant> <constant name="COLOR_NONE" value="0" enum="ColorFormat"> + Use when you are not using per-instance [Color]s. </constant> <constant name="COLOR_8BIT" value="1" enum="ColorFormat"> + Compress [Color] data into 8 bits when passing to shader. This uses less memory and can be faster, but the [Color] loses precision. </constant> <constant name="COLOR_FLOAT" value="2" enum="ColorFormat"> + The [Color] passed into [method set_instance_color] will use 4 floats. Use this for highest precision [Color]. </constant> <constant name="CUSTOM_DATA_NONE" value="0" enum="CustomDataFormat"> + Use when you are not using per-instance custom data. </constant> <constant name="CUSTOM_DATA_8BIT" value="1" enum="CustomDataFormat"> + Compress custom_data into 8 bits when passing to shader. This uses less memory and can be faster, but loses precision. </constant> <constant name="CUSTOM_DATA_FLOAT" value="2" enum="CustomDataFormat"> + The [Color] passed into [method set_instance_custom_data] will use 4 floats. Use this for highest precision. </constant> </constants> </class> diff --git a/doc/classes/Node.xml b/doc/classes/Node.xml index 02a8ee8e75..e872fee1cc 100644 --- a/doc/classes/Node.xml +++ b/doc/classes/Node.xml @@ -269,6 +269,15 @@ <description> </description> </method> + <method name="get_node_or_null" qualifiers="const"> + <return type="Node"> + </return> + <argument index="0" name="path" type="NodePath"> + </argument> + <description> + Similar to [method get_node], but does not raise an error when [code]path[/code] does not point to a valid [code]Node[/code]. + </description> + </method> <method name="get_parent" qualifiers="const"> <return type="Node"> </return> diff --git a/doc/classes/OS.xml b/doc/classes/OS.xml index f6ad71b6e2..5e71ed094e 100644 --- a/doc/classes/OS.xml +++ b/doc/classes/OS.xml @@ -159,6 +159,13 @@ <description> </description> </method> + <method name="get_current_video_driver" qualifiers="const"> + <return type="int" enum="OS.VideoDriver"> + </return> + <description> + Returns the currently used video driver, using one of the values from [enum OS.VideoDriver]. + </description> + </method> <method name="get_date" qualifiers="const"> <return type="Dictionary"> </return> @@ -459,14 +466,16 @@ <return type="int"> </return> <description> + Returns the number of video drivers supported on the current platform. </description> </method> <method name="get_video_driver_name" qualifiers="const"> <return type="String"> </return> - <argument index="0" name="driver" type="int"> + <argument index="0" name="driver" type="int" enum="OS.VideoDriver"> </argument> <description> + Returns the name of the video driver matching the given [code]driver[/code] index. This index is a value from [enum OS.VideoDriver], and you can use [method get_current_video_driver] to get the current backend's index. </description> </method> <method name="get_virtual_keyboard_height"> @@ -806,6 +815,12 @@ </member> </members> <constants> + <constant name="VIDEO_DRIVER_GLES2" value="1" enum="VideoDriver"> + The GLES2 rendering backend. It uses OpenGL ES 2.0 on mobile devices, OpenGL 2.1 on desktop platforms and WebGL 1.0 on the web. + </constant> + <constant name="VIDEO_DRIVER_GLES3" value="0" enum="VideoDriver"> + The GLES3 rendering backend. It uses OpenGL ES 3.0 on mobile devices, OpenGL 3.3 on desktop platforms and WebGL 2.0 on the web. + </constant> <constant name="DAY_SUNDAY" value="0" enum="Weekday"> Sunday. </constant> diff --git a/doc/classes/OccluderPolygon2D.xml b/doc/classes/OccluderPolygon2D.xml index 58ad268f05..b8adc4c96f 100644 --- a/doc/classes/OccluderPolygon2D.xml +++ b/doc/classes/OccluderPolygon2D.xml @@ -20,7 +20,7 @@ Set the direction of the occlusion culling when not [code]CULL_DISABLED[/code]. Default value [code]DISABLED[/code]. </member> <member name="polygon" type="PoolVector2Array" setter="set_polygon" getter="get_polygon"> - A [Vector2] array with the index for polygon's vertices positions. + A [Vector2] array with the index for polygon's vertices positions. Note that the returned value is a copy of the underlying array, rather than a reference. </member> </members> <constants> diff --git a/doc/classes/OptionButton.xml b/doc/classes/OptionButton.xml index c58c932b61..0f795b4bf8 100644 --- a/doc/classes/OptionButton.xml +++ b/doc/classes/OptionButton.xml @@ -71,7 +71,16 @@ <argument index="0" name="idx" type="int"> </argument> <description> - Return the ID of the item at index "idx". + Return the ID of the item at index [code]idx[/code]. + </description> + </method> + <method name="get_item_index" qualifiers="const"> + <return type="int"> + </return> + <argument index="0" name="id" type="int"> + </argument> + <description> + Return the index of the item with the given [code]id[/code]. </description> </method> <method name="get_item_metadata" qualifiers="const"> @@ -198,14 +207,14 @@ <argument index="0" name="ID" type="int"> </argument> <description> - This signal is emitted when user navigated to an item using [code]ui_up[/code] or [code]ui_down[/code] action. ID of the item selected is passed as argument (if no IDs were added, ID will be just the item index). + This signal is emitted when user navigated to an item using [code]ui_up[/code] or [code]ui_down[/code] action. ID of the item selected is passed as argument. </description> </signal> <signal name="item_selected"> <argument index="0" name="ID" type="int"> </argument> <description> - This signal is emitted when the current item was changed by the user. ID of the item selected is passed as argument (if no IDs were added, ID will be just the item index). + This signal is emitted when the current item was changed by the user. Index of the item selected is passed as argument. </description> </signal> </signals> diff --git a/doc/classes/Physics2DServer.xml b/doc/classes/Physics2DServer.xml index fe1465260f..341457a2b3 100644 --- a/doc/classes/Physics2DServer.xml +++ b/doc/classes/Physics2DServer.xml @@ -1112,6 +1112,8 @@ <constant name="SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS" value="6" enum="SpaceParameter"> Constant to set/get the default solver bias for all physics constraints. A solver bias is a factor controlling how much two objects "rebound", after violating a constraint, to avoid leaving them in that state because of numerical imprecision. </constant> + <constant name="SPACE_PARAM_TEST_MOTION_MIN_CONTACT_DEPTH" value="7" enum="SpaceParameter"> + </constant> <constant name="SHAPE_LINE" value="0" enum="ShapeType"> This is the constant for creating line shapes. A line shape is an infinite line with an origin point, and a normal. Thus, it can be used for front/behind checks. </constant> diff --git a/doc/classes/PhysicsDirectBodyState.xml b/doc/classes/PhysicsDirectBodyState.xml index 2b4125aef4..cf718f06b2 100644 --- a/doc/classes/PhysicsDirectBodyState.xml +++ b/doc/classes/PhysicsDirectBodyState.xml @@ -57,7 +57,7 @@ <argument index="1" name="j" type="Vector3"> </argument> <description> - Apply a positioned impulse (which will be affected by the body mass and shape). This is the equivalent of hitting a billiard ball with a cue: a force that is applied once, and only once. Both the impulse and the position are in global coordinates, and the position is relative to the object's origin. + Applies a positioned impulse to the body. An impulse is time independent! Applying an impulse every frame would result in a framerate dependent force. For this reason it should only be used when simulating one-time impacts. The position uses the rotation of the global coordinate system, but is centered at the object's origin. </description> </method> <method name="apply_torque_impulse"> diff --git a/doc/classes/PhysicsDirectSpaceState.xml b/doc/classes/PhysicsDirectSpaceState.xml index c4dc103b72..118010b3cf 100644 --- a/doc/classes/PhysicsDirectSpaceState.xml +++ b/doc/classes/PhysicsDirectSpaceState.xml @@ -21,7 +21,7 @@ </argument> <description> Checks whether the shape can travel to a point. The method will return an array with two floats between 0 and 1, both representing a fraction of [code]motion[/code]. The first is how far the shape can move without triggering a collision, and the second is the point at which a collision will occur. If no collision is detected, the returned array will be [code][1, 1][/code]. - If the shape can not move, the returned array will be [code][0, 0][/code]. + If the shape can not move, the returned array will be [code][0, 0][/code] under Bullet, and empty under GodotPhysics. </description> </method> <method name="collide_shape"> diff --git a/doc/classes/PhysicsServer.xml b/doc/classes/PhysicsServer.xml index e3ed43e7bc..b797e6ecf7 100644 --- a/doc/classes/PhysicsServer.xml +++ b/doc/classes/PhysicsServer.xml @@ -1595,6 +1595,8 @@ <constant name="SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS" value="7" enum="SpaceParameter"> Constant to set/get the default solver bias for all physics constraints. A solver bias is a factor controlling how much two objects "rebound", after violating a constraint, to avoid leaving them in that state because of numerical imprecision. </constant> + <constant name="SPACE_PARAM_TEST_MOTION_MIN_CONTACT_DEPTH" value="8" enum="SpaceParameter"> + </constant> <constant name="BODY_AXIS_LINEAR_X" value="1" enum="BodyAxis"> </constant> <constant name="BODY_AXIS_LINEAR_Y" value="2" enum="BodyAxis"> diff --git a/doc/classes/Polygon2D.xml b/doc/classes/Polygon2D.xml index 9803837e5d..31ee0a9490 100644 --- a/doc/classes/Polygon2D.xml +++ b/doc/classes/Polygon2D.xml @@ -99,7 +99,7 @@ The offset applied to each vertex. </member> <member name="polygon" type="PoolVector2Array" setter="set_polygon" getter="get_polygon"> - The polygon's list of vertices. The final point will be connected to the first. + The polygon's list of vertices. The final point will be connected to the first. Note that this returns a copy of the [PoolVector2Array] rather than a reference. </member> <member name="polygons" type="Array" setter="set_polygons" getter="get_polygons"> </member> diff --git a/doc/classes/PopupMenu.xml b/doc/classes/PopupMenu.xml index fe7dbe52b0..ea696e624a 100644 --- a/doc/classes/PopupMenu.xml +++ b/doc/classes/PopupMenu.xml @@ -378,7 +378,7 @@ <argument index="1" name="enable" type="bool"> </argument> <description> - Mark the item at index "idx" as a separator, which means that it would be displayed as a mere line. + Mark the item at index "idx" as a separator, which means that it would be displayed as a line. </description> </method> <method name="set_item_checked"> diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml index 6b53615535..1782edf25d 100644 --- a/doc/classes/ProjectSettings.xml +++ b/doc/classes/ProjectSettings.xml @@ -319,9 +319,6 @@ <member name="display/mouse_cursor/custom_image_hotspot" type="Vector2" setter="" getter=""> Hotspot for the custom mouse cursor image. </member> - <member name="display/window/allow_per_pixel_transparency" type="bool" setter="" getter=""> - Allow per pixel transparency in a Desktop window. This affects performance if not needed, so leave it off. - </member> <member name="display/window/dpi/allow_hidpi" type="bool" setter="" getter=""> Allow HiDPI display on Windows and OSX. On Desktop Linux, this can't be enabled or disabled. </member> @@ -331,9 +328,12 @@ <member name="display/window/handheld/orientation" type="String" setter="" getter=""> Default orientation for cell phone or tablet. </member> - <member name="display/window/per_pixel_transparency" type="bool" setter="" getter=""> + <member name="display/window/per_pixel_transparency/allowed" type="bool" setter="" getter=""> + Allow per pixel transparency in a Desktop window. This affects performance if not needed, so leave it off. + </member> + <member name="display/window/per_pixel_transparency/enabled" type="bool" setter="" getter=""> </member> - <member name="display/window/per_pixel_transparency_splash" type="bool" setter="" getter=""> + <member name="display/window/per_pixel_transparency/splash" type="bool" setter="" getter=""> </member> <member name="display/window/size/always_on_top" type="bool" setter="" getter=""> Force the window to be always on top. diff --git a/doc/classes/RandomNumberGenerator.xml b/doc/classes/RandomNumberGenerator.xml index 5badfba923..fff13402f1 100644 --- a/doc/classes/RandomNumberGenerator.xml +++ b/doc/classes/RandomNumberGenerator.xml @@ -43,7 +43,7 @@ <argument index="1" name="to" type="int"> </argument> <description> - Generates pseudo-random 32-bit signed integer between [code]from[/code] and [code]to[/code](inclusive). + Generates pseudo-random 32-bit signed integer between [code]from[/code] and [code]to[/code] (inclusive). </description> </method> <method name="randomize"> @@ -56,6 +56,7 @@ </methods> <members> <member name="seed" type="int" setter="set_seed" getter="get_seed"> + The seed used by the random number generator. A given seed will give a reproducible sequence of pseudo-random numbers. </member> </members> <constants> diff --git a/doc/classes/Resource.xml b/doc/classes/Resource.xml index fc42635ce2..4369f77abd 100644 --- a/doc/classes/Resource.xml +++ b/doc/classes/Resource.xml @@ -4,9 +4,10 @@ Base class for all resources. </brief_description> <description> - Resource is the base class for all resource types. Resources are primarily data containers. They are reference counted and freed when no longer in use. They are also loaded only once from disk, and further attempts to load the resource will return the same reference (all this in contrast to a [Node], which is not reference counted and can be instanced from disk as many times as desired). Resources can be saved externally on disk or bundled into another object, such as a [Node] or another resource. + Resource is the base class for all resource types, serving primarily as data containers. They are reference counted and freed when no longer in use. They are also loaded only once from disk, and further attempts to load the resource will return the same reference (all this in contrast to a [Node], which is not reference counted and can be instanced from disk as many times as desired). Resources can be saved externally on disk or bundled into another object, such as a [Node] or another resource. </description> <tutorials> + <link>https://docs.godotengine.org/en/stable/getting_started/step_by_step/resources.html</link> </tutorials> <demos> </demos> @@ -23,6 +24,7 @@ <argument index="0" name="subresources" type="bool" default="false"> </argument> <description> + Duplicates the resource, returning a new resource. By default, sub-resources are shared between resource copies for efficiency, this can be changed by passing [code]true[/code] to the [code]subresources[/code] argument. </description> </method> <method name="get_local_scene" qualifiers="const"> @@ -35,7 +37,7 @@ <return type="RID"> </return> <description> - Return the RID of the resource (or an empty RID). Many resources (such as [Texture], [Mesh], etc) are high level abstractions of resources stored in a server, so this function will return the original RID. + Returns the RID of the resource (or an empty RID). Many resources (such as [Texture], [Mesh], etc) are high level abstractions of resources stored in a server, so this function will return the original RID. </description> </method> <method name="setup_local_to_scene"> @@ -50,7 +52,7 @@ <argument index="0" name="path" type="String"> </argument> <description> - Set the path of the resource. Differs from set_path(), if another [code]Resource[/code] exists with "path" it over-takes it, instead of failing. + Sets the path of the resource. Differs from [code]set_path()[/code], if another [code]Resource[/code] exists with "path" it over-takes it, instead of failing. </description> </method> </methods> @@ -58,8 +60,10 @@ <member name="resource_local_to_scene" type="bool" setter="set_local_to_scene" getter="is_local_to_scene"> </member> <member name="resource_name" type="String" setter="set_name" getter="get_name"> + The name of the resource. This is an optional identifier. </member> <member name="resource_path" type="String" setter="set_path" getter="get_path"> + The path to the resource. In case it has its own file, it will return its filepath. If it's tied to the scene, it will return the scene's path, followed by the resource's index. </member> </members> <signals> diff --git a/doc/classes/ResourcePreloader.xml b/doc/classes/ResourcePreloader.xml index 002bcd891a..18d6e04d8e 100644 --- a/doc/classes/ResourcePreloader.xml +++ b/doc/classes/ResourcePreloader.xml @@ -4,7 +4,7 @@ Resource Preloader Node. </brief_description> <description> - Resource Preloader Node. This node is used to preload sub-resources inside a scene, so when the scene is loaded all the resources are ready to use and be retrieved from here. + This node is used to preload sub-resources inside a scene, so when the scene is loaded, all the resources are ready to use and can be retrieved from the preloader. </description> <tutorials> </tutorials> @@ -19,6 +19,7 @@ <argument index="1" name="resource" type="Resource"> </argument> <description> + Adds a resource to the preloader with the given [code]name[/code]. If a resource with the given [code]name[/code] already exists, the new resource will be renamed to "[code]name[/code] N" where N is an incrementing number starting from 2. </description> </method> <method name="get_resource" qualifiers="const"> @@ -27,14 +28,14 @@ <argument index="0" name="name" type="String"> </argument> <description> - Return the resource given a text-id. + Returns the resource associated to [code]name[/code]. </description> </method> <method name="get_resource_list" qualifiers="const"> <return type="PoolStringArray"> </return> <description> - Return the list of resources inside the preloader. + Returns the list of resources inside the preloader. </description> </method> <method name="has_resource" qualifiers="const"> @@ -43,7 +44,7 @@ <argument index="0" name="name" type="String"> </argument> <description> - Return true if the preloader has a given resource. + Returns true if the preloader contains a resource associated to [code]name[/code]. </description> </method> <method name="remove_resource"> @@ -52,7 +53,7 @@ <argument index="0" name="name" type="String"> </argument> <description> - Remove a resource from the preloader by text id. + Removes the resource associated to [code]name[/code] from the preloader. </description> </method> <method name="rename_resource"> @@ -63,7 +64,7 @@ <argument index="1" name="newname" type="String"> </argument> <description> - Rename a resource inside the preloader, from a text-id to a new text-id. + Renames a resource inside the preloader from [code]name[/code] to [code]newname[/code]. </description> </method> </methods> diff --git a/doc/classes/RigidBody.xml b/doc/classes/RigidBody.xml index 3f28156915..3c253c3bea 100644 --- a/doc/classes/RigidBody.xml +++ b/doc/classes/RigidBody.xml @@ -72,7 +72,7 @@ <argument index="1" name="impulse" type="Vector3"> </argument> <description> - Applies a positioned impulse which will be affected by the body mass and shape. This is the equivalent of hitting a billiard ball with a cue: a force that is applied once, and only once. Both the impulse and the position are in global coordinates, and the position is relative to the object's origin. + Applies a positioned impulse to the body. An impulse is time independent! Applying an impulse every frame would result in a framerate dependent force. For this reason it should only be used when simulating one-time impacts. The position uses the rotation of the global coordinate system, but is centered at the object's origin. </description> </method> <method name="apply_torque_impulse"> diff --git a/doc/classes/RigidBody2D.xml b/doc/classes/RigidBody2D.xml index 68e78ba5d4..9b74dbedb4 100644 --- a/doc/classes/RigidBody2D.xml +++ b/doc/classes/RigidBody2D.xml @@ -69,7 +69,7 @@ <argument index="1" name="impulse" type="Vector2"> </argument> <description> - Applies a positioned impulse to the body (which will be affected by the body mass and shape). This is the equivalent of hitting a billiard ball with a cue: a force that is applied instantaneously. Both the impulse and the offset from the body origin are in global coordinates. + Applies a positioned impulse to the body. An impulse is time independent! Applying an impulse every frame would result in a framerate dependent force. For this reason it should only be used when simulating one-time impacts (use the "_force" functions otherwise). The position uses the rotation of the global coordinate system, but is centered at the object's origin. </description> </method> <method name="apply_torque_impulse"> diff --git a/doc/classes/Skeleton2D.xml b/doc/classes/Skeleton2D.xml index 712b9ca2a5..d40b8a2fc7 100644 --- a/doc/classes/Skeleton2D.xml +++ b/doc/classes/Skeleton2D.xml @@ -30,6 +30,12 @@ </description> </method> </methods> + <signals> + <signal name="bone_setup_changed"> + <description> + </description> + </signal> + </signals> <constants> </constants> </class> diff --git a/doc/classes/StyleBox.xml b/doc/classes/StyleBox.xml index be21abe275..d8cc56cc8c 100644 --- a/doc/classes/StyleBox.xml +++ b/doc/classes/StyleBox.xml @@ -39,7 +39,8 @@ <argument index="0" name="margin" type="int" enum="Margin"> </argument> <description> - Return the offset of margin "margin" (see MARGIN_* enum). + Return the content margin offset for the specified margin + Positive values reduce size inwards, unlike [Control]'s margin values. </description> </method> <method name="get_minimum_size" qualifiers="const"> @@ -70,12 +71,22 @@ </methods> <members> <member name="content_margin_bottom" type="float" setter="set_default_margin" getter="get_default_margin"> + The bottom margin for the contents of this style box. Increasing this value reduces the space available to the contents from the bottom. + If this value is negative, it is ignored and a child-specific margin is used instead. For example for [StyleBoxFlat] the border thickness (if any) is used instead. + It is up to the code using this style box to decide what these contents are: for example, a [Button] respects this content margin for the textual contents of the button. + [method get_margin] should be used to fetch this value as consumer instead of reading these properties directly. This is because it correctly respects negative values and the fallback mentioned above. </member> <member name="content_margin_left" type="float" setter="set_default_margin" getter="get_default_margin"> + The left margin for the contents of this style box. Increasing this value reduces the space available to the contents from the left. + Refer to [member content_margin_bottom] for extra considerations. </member> <member name="content_margin_right" type="float" setter="set_default_margin" getter="get_default_margin"> + The right margin for the contents of this style box. Increasing this value reduces the space available to the contents from the right. + Refer to [member content_margin_bottom] for extra considerations. </member> <member name="content_margin_top" type="float" setter="set_default_margin" getter="get_default_margin"> + The top margin for the contents of this style box. Increasing this value reduces the space available to the contents from the top. + Refer to [member content_margin_bottom] for extra considerations. </member> </members> <constants> diff --git a/doc/classes/StyleBoxTexture.xml b/doc/classes/StyleBoxTexture.xml index d8c378fde2..806ed1941a 100644 --- a/doc/classes/StyleBoxTexture.xml +++ b/doc/classes/StyleBoxTexture.xml @@ -42,28 +42,49 @@ <member name="draw_center" type="bool" setter="set_draw_center" getter="is_draw_center_enabled"> </member> <member name="expand_margin_bottom" type="float" setter="set_expand_margin_size" getter="get_expand_margin_size"> + Expands the bottom margin of this style box when drawing, causing it be drawn larger than requested. </member> <member name="expand_margin_left" type="float" setter="set_expand_margin_size" getter="get_expand_margin_size"> + Expands the left margin of this style box when drawing, causing it be drawn larger than requested. </member> <member name="expand_margin_right" type="float" setter="set_expand_margin_size" getter="get_expand_margin_size"> + Expands the right margin of this style box when drawing, causing it be drawn larger than requested. </member> <member name="expand_margin_top" type="float" setter="set_expand_margin_size" getter="get_expand_margin_size"> + Expands the top margin of this style box when drawing, causing it be drawn larger than requested. </member> <member name="margin_bottom" type="float" setter="set_margin_size" getter="get_margin_size"> + Increases the bottom margin of the 3x3 texture box. + A higher value means more of the source texture is considered to be part of the bottom border of the 3x3 box. + This is also the value used as fallback for [member StyleBox.content_margin_bottom] if it is negative. </member> <member name="margin_left" type="float" setter="set_margin_size" getter="get_margin_size"> + Increases the left margin of the 3x3 texture box. + A higher value means more of the source texture is considered to be part of the left border of the 3x3 box. + This is also the value used as fallback for [member StyleBox.content_margin_left] if it is negative. </member> <member name="margin_right" type="float" setter="set_margin_size" getter="get_margin_size"> + Increases the right margin of the 3x3 texture box. + A higher value means more of the source texture is considered to be part of the right border of the 3x3 box. + This is also the value used as fallback for [member StyleBox.content_margin_right] if it is negative. </member> <member name="margin_top" type="float" setter="set_margin_size" getter="get_margin_size"> + Increases the top margin of the 3x3 texture box. + A higher value means more of the source texture is considered to be part of the top border of the 3x3 box. + This is also the value used as fallback for [member StyleBox.content_margin_top] if it is negative. </member> <member name="modulate_color" type="Color" setter="set_modulate" getter="get_modulate"> + Modulates the color of the texture when this style box is drawn. </member> <member name="normal_map" type="Texture" setter="set_normal_map" getter="get_normal_map"> + The normal map to use when drawing this style box. </member> <member name="region_rect" type="Rect2" setter="set_region_rect" getter="get_region_rect"> + Species a sub region of the texture to use. + This is equivalent to first wrapping the texture in an [AtlasTexture] with the same region. </member> <member name="texture" type="Texture" setter="set_texture" getter="get_texture"> + The texture to use when drawing this style box. </member> </members> <signals> diff --git a/doc/classes/SurfaceTool.xml b/doc/classes/SurfaceTool.xml index fd158587e5..587b0190fe 100644 --- a/doc/classes/SurfaceTool.xml +++ b/doc/classes/SurfaceTool.xml @@ -78,7 +78,7 @@ <method name="add_triangle_fan"> <return type="void"> </return> - <argument index="0" name="vertexes" type="PoolVector3Array"> + <argument index="0" name="vertices" type="PoolVector3Array"> </argument> <argument index="1" name="uvs" type="PoolVector2Array" default="PoolVector2Array( )"> </argument> diff --git a/doc/classes/TabContainer.xml b/doc/classes/TabContainer.xml index 04285b62df..3c5bc25def 100644 --- a/doc/classes/TabContainer.xml +++ b/doc/classes/TabContainer.xml @@ -216,6 +216,8 @@ </theme_item> <theme_item name="tab_bg" type="StyleBox"> </theme_item> + <theme_item name="tab_disabled" type="StyleBox"> + </theme_item> <theme_item name="tab_fg" type="StyleBox"> </theme_item> <theme_item name="top_margin" type="int"> diff --git a/doc/classes/Tabs.xml b/doc/classes/Tabs.xml index de57250d8b..b22d9d73da 100644 --- a/doc/classes/Tabs.xml +++ b/doc/classes/Tabs.xml @@ -279,6 +279,8 @@ </theme_item> <theme_item name="tab_bg" type="StyleBox"> </theme_item> + <theme_item name="tab_disabled" type="StyleBox"> + </theme_item> <theme_item name="tab_fg" type="StyleBox"> </theme_item> <theme_item name="top_margin" type="int"> diff --git a/doc/classes/TileMap.xml b/doc/classes/TileMap.xml index 4849d768f5..fe3b2118a3 100644 --- a/doc/classes/TileMap.xml +++ b/doc/classes/TileMap.xml @@ -34,7 +34,7 @@ <argument index="1" name="y" type="int"> </argument> <description> - Returns the tile index of the given cell. + Returns the tile index of the given cell. If no tile exists in the cell, returns [constant INVALID_CELL]. </description> </method> <method name="get_cell_autotile_coord" qualifiers="const"> @@ -53,7 +53,7 @@ <argument index="0" name="position" type="Vector2"> </argument> <description> - Returns the tile index of the cell given by a Vector2. + Returns the tile index of the cell given by a Vector2. If no tile exists in the cell, returns [constant INVALID_CELL]. </description> </method> <method name="get_collision_layer_bit" qualifiers="const"> diff --git a/doc/classes/UndoRedo.xml b/doc/classes/UndoRedo.xml index 93806ac326..8d98bcfdb0 100644 --- a/doc/classes/UndoRedo.xml +++ b/doc/classes/UndoRedo.xml @@ -8,22 +8,22 @@ Common behavior is to create an action, then add do/undo calls to functions or property changes, then committing the action. Here's an example on how to add an action to Godot editor's own 'undoredo': [codeblock] - var undoredo = get_undo_redo() # method of EditorPlugin + var undo_redo = get_undo_redo() # Method of EditorPlugin. func do_something(): - pass # put your code here + pass # Put your code here. func undo_something(): - pass # put here the code that reverts what's done by "do_something()" + pass # Put here the code that reverts what's done by "do_something()". func _on_MyButton_pressed(): var node = get_node("MyNode2D") - undoredo.create_action("Move the node") - undoredo.add_do_method(self, "do_something") - undoredo.add_undo_method(self, "undo_something") - undoredo.add_do_property(node, "position", Vector2(100,100)) - undoredo.add_undo_property(node, "position", node.position) - undoredo.commit_action() + undo_redo.create_action("Move the node") + undo_redo.add_do_method(self, "do_something") + undo_redo.add_undo_method(self, "undo_something") + undo_redo.add_do_property(node, "position", Vector2(100,100)) + undo_redo.add_undo_property(node, "position", node.position) + undo_redo.commit_action() [/codeblock] [method create_action], [method add_do_method], [method add_undo_method], [method add_do_property], [method add_undo_property], and [method commit_action] should be called one after the other, like in the example. Not doing so could lead to crashes. If you don't need to register a method you can leave [method add_do_method] and [method add_undo_method] out, and so it goes for properties. You can register more than one method/property. @@ -125,6 +125,7 @@ </argument> <description> Create a new action. After this is called, do all your calls to [method add_do_method], [method add_undo_method], [method add_do_property], and [method add_undo_property], then commit the action with [method commit_action]. + The way actions are merged is dictated by the [code]merge_mode[/code] argument. See [enum MergeMode] for details. </description> </method> <method name="get_current_action_name" qualifiers="const"> @@ -159,10 +160,13 @@ </methods> <constants> <constant name="MERGE_DISABLE" value="0" enum="MergeMode"> + Makes [code]do[/code]/[code]undo[/code] operations stay in separate actions. </constant> <constant name="MERGE_ENDS" value="1" enum="MergeMode"> + Makes so that the action's [code]do[/code] operation is from the first action created and the [code]undo[/code] operation is from the last subsequent action with the same name. </constant> <constant name="MERGE_ALL" value="2" enum="MergeMode"> + Makes subsequent actions with the same name be merged into one. </constant> </constants> </class> diff --git a/doc/classes/Viewport.xml b/doc/classes/Viewport.xml index 880dc43c90..09891ca889 100644 --- a/doc/classes/Viewport.xml +++ b/doc/classes/Viewport.xml @@ -80,7 +80,11 @@ <return type="ViewportTexture"> </return> <description> - Returns the viewport's texture. + Returns the viewport's texture. Note that due to the way OpenGL works, the resulting [ViewportTexture] is flipped vertically. You can use [method Image.flip_y] on the result of [method Texture.get_data] to flip it back, for example: + [codeblock] + var img = get_viewport().get_texture().get_data() + img.flip_y() + [/codeblock] </description> </method> <method name="get_viewport_rid" qualifiers="const"> diff --git a/doc/classes/int.xml b/doc/classes/int.xml index 4855fa2848..7175b9fd88 100644 --- a/doc/classes/int.xml +++ b/doc/classes/int.xml @@ -4,7 +4,21 @@ Integer built-in type. </brief_description> <description> - Integer built-in type. + Signed 64-bit integer type. + It can take values in the interval [code][-2^63, 2^63 - 1][/code], i.e. [code][-9223372036854775808, 9223372036854775807][/code]. Exceeding those bounds will wrap around. + [code]int[/code] is a [Variant] type, and will thus be used when assigning an integer value to a [Variant]. It can also be enforced with the [code]: int[/code] type hint. + [codeblock] + var my_variant = 0 # int, value 0 + my_variant += 4.2 # float, value 4.2 + var my_int: int = 1 # int, value 1 + my_int = 4.2 # int, value 4, the right value is implicitly cast to int + my_int = int("6.7") # int, value 6, the String is explicitly cast with [method int] + + var max_int = 9223372036854775807 + print(max_int) # 9223372036854775807, OK + max_int += 1 + print(max_int) # -9223372036854775808, we overflowed and wrapped around + [/codeblock] </description> <tutorials> </tutorials> diff --git a/drivers/SCsub b/drivers/SCsub index 320d4dc4bb..583973c025 100644 --- a/drivers/SCsub +++ b/drivers/SCsub @@ -13,7 +13,6 @@ SConscript('alsa/SCsub') SConscript('coreaudio/SCsub') SConscript('pulseaudio/SCsub') if (env["platform"] == "windows"): - SConscript("rtaudio/SCsub") SConscript("wasapi/SCsub") if env['xaudio2']: SConscript("xaudio2/SCsub") diff --git a/drivers/alsamidi/alsa_midi.cpp b/drivers/alsamidi/midi_driver_alsamidi.cpp index cd90c8912b..aae0ae0216 100644 --- a/drivers/alsamidi/alsa_midi.cpp +++ b/drivers/alsamidi/midi_driver_alsamidi.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* alsa_midi.cpp */ +/* midi_driver_alsamidi.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -30,7 +30,7 @@ #ifdef ALSAMIDI_ENABLED -#include "alsa_midi.h" +#include "midi_driver_alsamidi.h" #include "core/os/os.h" #include "core/print_string.h" @@ -199,4 +199,4 @@ MIDIDriverALSAMidi::~MIDIDriverALSAMidi() { close(); } -#endif +#endif // ALSAMIDI_ENABLED diff --git a/drivers/alsamidi/alsa_midi.h b/drivers/alsamidi/midi_driver_alsamidi.h index 054a7b474e..b6956cc32f 100644 --- a/drivers/alsamidi/alsa_midi.h +++ b/drivers/alsamidi/midi_driver_alsamidi.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* alsa_midi.h */ +/* midi_driver_alsamidi.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -30,8 +30,8 @@ #ifdef ALSAMIDI_ENABLED -#ifndef ALSA_MIDI_H -#define ALSA_MIDI_H +#ifndef MIDI_DRIVER_ALSAMIDI_H +#define MIDI_DRIVER_ALSAMIDI_H #include "core/os/midi_driver.h" #include "core/os/mutex.h" @@ -65,5 +65,5 @@ public: virtual ~MIDIDriverALSAMidi(); }; -#endif -#endif +#endif // MIDI_DRIVER_ALSAMIDI_H +#endif // ALSAMIDI_ENABLED diff --git a/drivers/coremidi/core_midi.cpp b/drivers/coremidi/midi_driver_coremidi.cpp index 7d3477213f..7a92ac0702 100644 --- a/drivers/coremidi/core_midi.cpp +++ b/drivers/coremidi/midi_driver_coremidi.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* core_midi.cpp */ +/* midi_driver_coremidi.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -30,7 +30,7 @@ #ifdef COREMIDI_ENABLED -#include "core_midi.h" +#include "midi_driver_coremidi.h" #include "core/print_string.h" @@ -120,4 +120,4 @@ MIDIDriverCoreMidi::~MIDIDriverCoreMidi() { close(); } -#endif +#endif // COREMIDI_ENABLED diff --git a/drivers/coremidi/core_midi.h b/drivers/coremidi/midi_driver_coremidi.h index 7a10b5548e..23c2a19812 100644 --- a/drivers/coremidi/core_midi.h +++ b/drivers/coremidi/midi_driver_coremidi.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* core_midi.h */ +/* midi_driver_coremidi.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -30,8 +30,8 @@ #ifdef COREMIDI_ENABLED -#ifndef CORE_MIDI_H -#define CORE_MIDI_H +#ifndef MIDI_DRIVER_COREMIDI_H +#define MIDI_DRIVER_COREMIDI_H #include "core/os/midi_driver.h" #include "core/vector.h" @@ -58,5 +58,5 @@ public: virtual ~MIDIDriverCoreMidi(); }; -#endif -#endif +#endif // MIDI_DRIVER_COREMIDI_H +#endif // COREMIDI_ENABLED diff --git a/drivers/gles2/rasterizer_canvas_gles2.cpp b/drivers/gles2/rasterizer_canvas_gles2.cpp index 64e4dbdab4..9a49d5a7e4 100644 --- a/drivers/gles2/rasterizer_canvas_gles2.cpp +++ b/drivers/gles2/rasterizer_canvas_gles2.cpp @@ -112,25 +112,21 @@ void RasterizerCanvasGLES2::_set_uniforms() { void RasterizerCanvasGLES2::canvas_begin() { state.canvas_shader.bind(); - bool transparent = false; + state.using_transparent_rt = false; if (storage->frame.current_rt) { glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo); - glColorMask(1, 1, 1, 1); - transparent = storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]; + state.using_transparent_rt = storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]; } if (storage->frame.clear_request) { - glColorMask(true, true, true, true); glClearColor(storage->frame.clear_request_color.r, storage->frame.clear_request_color.g, storage->frame.clear_request_color.b, - transparent ? storage->frame.clear_request_color.a : 1.0); + state.using_transparent_rt ? storage->frame.clear_request_color.a : 1.0); glClear(GL_COLOR_BUFFER_BIT); storage->frame.clear_request = false; } - glColorMask(1, 1, 1, transparent ? 1 : 0); - /* if (storage->frame.current_rt) { glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo); @@ -186,7 +182,7 @@ void RasterizerCanvasGLES2::canvas_end() { state.using_texture_rect = false; state.using_skeleton = false; state.using_ninepatch = false; - glColorMask(1, 1, 1, 1); + state.using_transparent_rt = false; } RasterizerStorageGLES2::Texture *RasterizerCanvasGLES2::_bind_canvas_texture(const RID &p_texture, const RID &p_normal_map) { @@ -576,8 +572,15 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); } } else { + static const Vector2 uvs[4] = { + Vector2(0.0, 0.0), + Vector2(0.0, 1.0), + Vector2(1.0, 1.0), + Vector2(1.0, 0.0), + }; + state.canvas_shader.set_uniform(CanvasShaderGLES2::COLOR_TEXPIXEL_SIZE, Vector2()); - _draw_gui_primitive(4, points, NULL, NULL); + _draw_gui_primitive(4, points, NULL, uvs); } } else { @@ -844,11 +847,11 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur int indices[num_points * 3]; - for (int i = 0; i < num_points; i++) { - points[i] = circle->pos + Vector2(Math::sin(i * Math_PI * 2.0 / num_points), Math::cos(i * Math_PI * 2.0 / num_points)) * circle->radius; - indices[i * 3 + 0] = i; - indices[i * 3 + 1] = (i + 1) % num_points; - indices[i * 3 + 2] = num_points; + for (int j = 0; j < num_points; j++) { + points[j] = circle->pos + Vector2(Math::sin(j * Math_PI * 2.0 / num_points), Math::cos(j * Math_PI * 2.0 / num_points)) * circle->radius; + indices[j * 3 + 0] = j; + indices[j * 3 + 1] = (j + 1) % num_points; + indices[j * 3 + 2] = num_points; } _bind_canvas_texture(RID(), RID()); @@ -906,13 +909,13 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, s->index_id); } - for (int i = 0; i < VS::ARRAY_MAX - 1; i++) { - if (s->attribs[i].enabled) { - glEnableVertexAttribArray(i); - glVertexAttribPointer(s->attribs[i].index, s->attribs[i].size, s->attribs[i].type, s->attribs[i].normalized, s->attribs[i].stride, (uint8_t *)0 + s->attribs[i].offset); + for (int k = 0; k < VS::ARRAY_MAX - 1; k++) { + if (s->attribs[k].enabled) { + glEnableVertexAttribArray(k); + glVertexAttribPointer(s->attribs[k].index, s->attribs[k].size, s->attribs[k].type, s->attribs[k].normalized, s->attribs[k].stride, (uint8_t *)0 + s->attribs[k].offset); } else { - glDisableVertexAttribArray(i); - switch (i) { + glDisableVertexAttribArray(k); + switch (k) { case VS::ARRAY_NORMAL: { glVertexAttrib4f(VS::ARRAY_NORMAL, 0.0, 0.0, 1, 1); } break; @@ -932,8 +935,8 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur } } - for (int i = 1; i < VS::ARRAY_MAX - 1; i++) { - glDisableVertexAttribArray(i); + for (int j = 1; j < VS::ARRAY_MAX - 1; j++) { + glDisableVertexAttribArray(j); } } @@ -995,13 +998,13 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, s->index_id); } - for (int i = 0; i < VS::ARRAY_MAX - 1; i++) { - if (s->attribs[i].enabled) { - glEnableVertexAttribArray(i); - glVertexAttribPointer(s->attribs[i].index, s->attribs[i].size, s->attribs[i].type, s->attribs[i].normalized, s->attribs[i].stride, (uint8_t *)0 + s->attribs[i].offset); + for (int k = 0; k < VS::ARRAY_MAX - 1; k++) { + if (s->attribs[k].enabled) { + glEnableVertexAttribArray(k); + glVertexAttribPointer(s->attribs[k].index, s->attribs[k].size, s->attribs[k].type, s->attribs[k].normalized, s->attribs[k].stride, (uint8_t *)0 + s->attribs[k].offset); } else { - glDisableVertexAttribArray(i); - switch (i) { + glDisableVertexAttribArray(k); + switch (k) { case VS::ARRAY_NORMAL: { glVertexAttrib4f(VS::ARRAY_NORMAL, 0.0, 0.0, 1, 1); } break; @@ -1014,8 +1017,8 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur } } - for (int i = 0; i < amount; i++) { - const float *buffer = base_buffer + i * stride; + for (int k = 0; k < amount; k++) { + const float *buffer = base_buffer + k * stride; { @@ -1165,7 +1168,7 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur } } -void RasterizerCanvasGLES2::_copy_texscreen(const Rect2 &p_rect) { +void RasterizerCanvasGLES2::_copy_screen(const Rect2 &p_rect) { if (storage->frame.current_rt->copy_screen_effect.color == 0) { ERR_EXPLAIN("Can't use screen texture copying in a render target configured without copy buffers"); @@ -1174,8 +1177,6 @@ void RasterizerCanvasGLES2::_copy_texscreen(const Rect2 &p_rect) { glDisable(GL_BLEND); - state.canvas_texscreen_used = true; - Vector2 wh(storage->frame.current_rt->width, storage->frame.current_rt->height); Color copy_section(p_rect.position.x / wh.x, p_rect.position.y / wh.y, p_rect.size.x / wh.x, p_rect.size.y / wh.y); @@ -1184,13 +1185,12 @@ void RasterizerCanvasGLES2::_copy_texscreen(const Rect2 &p_rect) { storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_COPY_SECTION, true); } + storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_NO_ALPHA, !state.using_transparent_rt); + glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->copy_screen_effect.fbo); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->color); - glClearColor(1, 0, 1, 1); - glClear(GL_COLOR_BUFFER_BIT); - storage->shaders.copy.bind(); storage->shaders.copy.set_uniform(CopyShaderGLES2::COPY_SECTION, copy_section); @@ -1216,16 +1216,23 @@ void RasterizerCanvasGLES2::_copy_texscreen(const Rect2 &p_rect) { _draw_polygon(indexpos, 6, 4, vertpos, uvpos, NULL, false); storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_COPY_SECTION, false); + storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_NO_ALPHA, false); glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo); //back to front + glEnable(GL_BLEND); +} + +void RasterizerCanvasGLES2::_copy_texscreen(const Rect2 &p_rect) { + + state.canvas_texscreen_used = true; + + _copy_screen(p_rect); // back to canvas, force rebind state.using_texture_rect = false; state.canvas_shader.bind(); _bind_canvas_texture(state.current_tex, state.current_normal); _set_uniforms(); - - glEnable(GL_BLEND); } void RasterizerCanvasGLES2::canvas_render_items(Item *p_item_list, int p_z, const Color &p_modulate, Light *p_light, const Transform2D &p_base_transform) { @@ -1878,6 +1885,8 @@ void RasterizerCanvasGLES2::draw_window_margins(int *black_margin, RID *black_im draw_generic_textured_rect(Rect2(0, window_h - black_margin[MARGIN_BOTTOM], window_w, black_margin[MARGIN_BOTTOM]), Rect2(0, 0, 1, 1)); } + + canvas_end(); } void RasterizerCanvasGLES2::initialize() { @@ -1998,6 +2007,7 @@ void RasterizerCanvasGLES2::initialize() { state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_PIXEL_SNAP, GLOBAL_DEF("rendering/quality/2d/use_pixel_snap", false)); state.using_light = NULL; + state.using_transparent_rt = false; } void RasterizerCanvasGLES2::finalize() { diff --git a/drivers/gles2/rasterizer_canvas_gles2.h b/drivers/gles2/rasterizer_canvas_gles2.h index 221427198a..af41e91e0c 100644 --- a/drivers/gles2/rasterizer_canvas_gles2.h +++ b/drivers/gles2/rasterizer_canvas_gles2.h @@ -93,6 +93,7 @@ public: Transform vp; Light *using_light; bool using_shadow; + bool using_transparent_rt; } state; @@ -118,6 +119,7 @@ public: _FORCE_INLINE_ void _draw_generic(GLuint p_primitive, int p_vertex_count, const Vector2 *p_vertices, const Vector2 *p_uvs, const Color *p_colors, bool p_singlecolor); _FORCE_INLINE_ void _canvas_item_render_commands(Item *p_item, Item *current_clip, bool &reclip, RasterizerStorageGLES2::Material *p_material); + void _copy_screen(const Rect2 &p_rect); _FORCE_INLINE_ void _copy_texscreen(const Rect2 &p_rect); virtual void canvas_render_items(Item *p_item_list, int p_z, const Color &p_modulate, Light *p_light, const Transform2D &p_base_transform); diff --git a/drivers/gles2/rasterizer_scene_gles2.cpp b/drivers/gles2/rasterizer_scene_gles2.cpp index 2c52895bda..a7becdde24 100644 --- a/drivers/gles2/rasterizer_scene_gles2.cpp +++ b/drivers/gles2/rasterizer_scene_gles2.cpp @@ -1120,10 +1120,10 @@ void RasterizerSceneGLES2::_fill_render_list(InstanceBase **p_cull_result, int p int num_surfaces = mesh->surfaces.size(); - for (int i = 0; i < num_surfaces; i++) { - int material_index = instance->materials[i].is_valid() ? i : -1; + for (int j = 0; j < num_surfaces; j++) { + int material_index = instance->materials[j].is_valid() ? j : -1; - RasterizerStorageGLES2::Surface *surface = mesh->surfaces[i]; + RasterizerStorageGLES2::Surface *surface = mesh->surfaces[j]; _add_geometry(surface, instance, NULL, material_index, p_depth_pass, p_shadow_pass); } @@ -1143,8 +1143,8 @@ void RasterizerSceneGLES2::_fill_render_list(InstanceBase **p_cull_result, int p int ssize = mesh->surfaces.size(); - for (int i = 0; i < ssize; i++) { - RasterizerStorageGLES2::Surface *s = mesh->surfaces[i]; + for (int j = 0; j < ssize; j++) { + RasterizerStorageGLES2::Surface *s = mesh->surfaces[j]; _add_geometry(s, instance, multi_mesh, -1, p_depth_pass, p_shadow_pass); } } break; @@ -1178,9 +1178,19 @@ bool RasterizerSceneGLES2::_setup_material(RasterizerStorageGLES2::Material *p_m state.scene_shader.set_custom_shader(p_material->shader->custom_code_id); + if (p_material->shader->spatial.uses_screen_texture && storage->frame.current_rt) { + glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 4); + glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->copy_screen_effect.color); + } + + if (p_material->shader->spatial.uses_depth_texture && storage->frame.current_rt) { + glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 4); + glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->depth); + } + bool shader_rebind = state.scene_shader.bind(); - if (p_material->shader->spatial.no_depth_test) { + if (p_material->shader->spatial.no_depth_test || p_material->shader->spatial.uses_depth_texture) { glDisable(GL_DEPTH_TEST); } else { glEnable(GL_DEPTH_TEST); @@ -1190,19 +1200,16 @@ bool RasterizerSceneGLES2::_setup_material(RasterizerStorageGLES2::Material *p_m case RasterizerStorageGLES2::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS: case RasterizerStorageGLES2::Shader::Spatial::DEPTH_DRAW_OPAQUE: { - glDepthMask(!p_alpha_pass); + glDepthMask(!p_alpha_pass && !p_material->shader->spatial.uses_depth_texture); } break; case RasterizerStorageGLES2::Shader::Spatial::DEPTH_DRAW_ALWAYS: { - glDepthMask(GL_TRUE); + glDepthMask(GL_TRUE && !p_material->shader->spatial.uses_depth_texture); } break; case RasterizerStorageGLES2::Shader::Spatial::DEPTH_DRAW_NEVER: { glDepthMask(GL_FALSE); } break; } - // TODO whyyyyy???? - p_reverse_cull = true; - switch (p_material->shader->spatial.cull_mode) { case RasterizerStorageGLES2::Shader::Spatial::CULL_MODE_DISABLED: { glDisable(GL_CULL_FACE); @@ -1564,6 +1571,8 @@ void RasterizerSceneGLES2::_render_geometry(RenderList::Element *p_element) { } else { glVertexAttrib4fv(INSTANCE_ATTRIB_BASE + 3, buffer + color_ofs); } + } else { + glVertexAttrib4f(INSTANCE_ATTRIB_BASE + 3, 1.0, 1.0, 1.0, 1.0); } if (multi_mesh->custom_data_floats) { @@ -1786,6 +1795,9 @@ void RasterizerSceneGLES2::_setup_light(LightInstance *light, ShadowAtlas *shado Color color = light_ptr->color * sign * energy * Math_PI; state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_COLOR, color); + Color shadow_color = light_ptr->shadow_color.to_linear(); + state.scene_shader.set_uniform(SceneShaderGLES2::SHADOW_COLOR, shadow_color); + //specific parameters switch (light_ptr->type) { @@ -2337,7 +2349,7 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements, Transform sky_orientation(p_env->sky_orientation, Vector3(0.0, 0.0, 0.0)); state.scene_shader.set_uniform(SceneShaderGLES2::RADIANCE_INVERSE_XFORM, sky_orientation.affine_inverse() * p_view_transform); } else { - // would be a bit weird if we dont have this... + // would be a bit weird if we don't have this... state.scene_shader.set_uniform(SceneShaderGLES2::RADIANCE_INVERSE_XFORM, p_view_transform); } } @@ -2352,7 +2364,7 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements, } else { state.scene_shader.set_uniform(SceneShaderGLES2::BG_ENERGY, 1.0); state.scene_shader.set_uniform(SceneShaderGLES2::AMBIENT_SKY_CONTRIBUTION, 1.0); - state.scene_shader.set_uniform(SceneShaderGLES2::AMBIENT_COLOR, Color(1.0, 1.0, 1.0, 1.0)); + state.scene_shader.set_uniform(SceneShaderGLES2::AMBIENT_COLOR, state.default_ambient); state.scene_shader.set_uniform(SceneShaderGLES2::AMBIENT_ENERGY, 1.0); } @@ -2464,7 +2476,6 @@ void RasterizerSceneGLES2::_draw_sky(RasterizerStorageGLES2::Sky *p_sky, const C glDisable(GL_CULL_FACE); glDisable(GL_BLEND); glDepthFunc(GL_LEQUAL); - glColorMask(1, 1, 1, 1); // Camera CameraMatrix camera; @@ -2555,11 +2566,19 @@ void RasterizerSceneGLES2::_draw_sky(RasterizerStorageGLES2::Sky *p_sky, const C void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) { + Transform cam_transform = p_cam_transform; + GLuint current_fb = 0; Environment *env = NULL; int viewport_width, viewport_height; bool probe_interior = false; + bool reverse_cull = false; + + if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_VFLIP]) { + cam_transform.basis.set_axis(1, -cam_transform.basis.get_axis(1)); + reverse_cull = true; + } if (p_reflection_probe.is_valid()) { ReflectionProbeInstance *probe = reflection_probe_instance_owner.getornull(p_reflection_probe); @@ -2586,6 +2605,7 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const viewport_height = storage->frame.current_rt->height; } + state.used_screen_texture = false; state.viewport_size.x = viewport_width; state.viewport_size.y = viewport_height; state.screen_pixel_size.x = 1.0 / viewport_width; @@ -2594,7 +2614,7 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const //push back the directional lights if (p_light_cull_count) { - //harcoded limit of 256 lights + //hardcoded limit of 256 lights render_light_instance_count = MIN(RenderList::MAX_LIGHTS, p_light_cull_count); render_light_instances = (LightInstance **)alloca(sizeof(LightInstance *) * render_light_instance_count); render_directional_lights = 0; @@ -2608,7 +2628,7 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const if (light->light_ptr->type == VS::LIGHT_DIRECTIONAL) { render_directional_lights++; - //as goin in reverse, directional lights are always first anyway + //as going in reverse, directional lights are always first anyway } light->light_index = index; @@ -2657,7 +2677,7 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const // clear color - Color clear_color(0, 0, 0, 0); + Color clear_color(0, 0, 0, 1); if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) { clear_color = Color(0, 0, 0, 0); @@ -2678,6 +2698,8 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const glClearColor(clear_color.r, clear_color.g, clear_color.b, clear_color.a); } + state.default_ambient = Color(clear_color.r, clear_color.g, clear_color.b, 1.0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1); @@ -2709,7 +2731,7 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const if (env && env->bg_mode == VS::ENV_BG_SKY && (!storage->frame.current_rt || !storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT])) { if (sky && sky->panorama.is_valid()) { - _draw_sky(sky, p_cam_projection, p_cam_transform, false, env->sky_custom_fov, env->bg_energy, env->sky_orientation); + _draw_sky(sky, p_cam_projection, cam_transform, false, env->sky_custom_fov, env->bg_energy, env->sky_orientation); } } @@ -2719,8 +2741,12 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const // render opaque things first render_list.sort_by_key(false); - _render_render_list(render_list.elements, render_list.element_count, p_cam_transform, p_cam_projection, p_shadow_atlas, env, env_radiance_tex, 0.0, 0.0, false, false, false); + _render_render_list(render_list.elements, render_list.element_count, cam_transform, p_cam_projection, p_shadow_atlas, env, env_radiance_tex, 0.0, 0.0, reverse_cull, false, false); + if (storage->frame.current_rt && state.used_screen_texture) { + //copy screen texture + storage->canvas->_copy_screen(Rect2()); + } // alpha pass glBlendEquation(GL_FUNC_ADD); @@ -2728,7 +2754,7 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const render_list.sort_by_depth(true); - _render_render_list(&render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, p_cam_transform, p_cam_projection, p_shadow_atlas, env, env_radiance_tex, 0.0, 0.0, false, true, false); + _render_render_list(&render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, cam_transform, p_cam_projection, p_shadow_atlas, env, env_radiance_tex, 0.0, 0.0, reverse_cull, true, false); glDisable(GL_DEPTH_TEST); @@ -3041,7 +3067,9 @@ void RasterizerSceneGLES2::render_shadow(RID p_light, RID p_shadow_atlas, int p_ } } - glViewport(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height); + if (storage->frame.current_rt) { + glViewport(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height); + } glColorMask(1, 1, 1, 1); } @@ -3224,6 +3252,8 @@ void RasterizerSceneGLES2::initialize() { } shadow_filter_mode = SHADOW_FILTER_NEAREST; + + glFrontFace(GL_CW); } void RasterizerSceneGLES2::iteration() { diff --git a/drivers/gles2/rasterizer_scene_gles2.h b/drivers/gles2/rasterizer_scene_gles2.h index 0d917f4da2..aab9ae0fdc 100644 --- a/drivers/gles2/rasterizer_scene_gles2.h +++ b/drivers/gles2/rasterizer_scene_gles2.h @@ -103,6 +103,7 @@ public: GLuint sky_verts; GLuint immediate_buffer; + Color default_ambient; // ResolveShaderGLES3 resolve_shader; // ScreenSpaceReflectionShaderGLES3 ssr_shader; diff --git a/drivers/gles2/rasterizer_storage_gles2.cpp b/drivers/gles2/rasterizer_storage_gles2.cpp index d00d572ccf..9def9d27e7 100644 --- a/drivers/gles2/rasterizer_storage_gles2.cpp +++ b/drivers/gles2/rasterizer_storage_gles2.cpp @@ -1230,6 +1230,10 @@ void RasterizerStorageGLES2::_update_shader(Shader *p_shader) const { actions = &shaders.actions_scene; actions->uniforms = &p_shader->uniforms; + + if (p_shader->spatial.uses_screen_texture && p_shader->spatial.uses_depth_texture) { + WARN_PRINT("Using both SCREEN_TEXTURE and DEPTH_TEXTURE is not supported in GLES2"); + } } break; default: { @@ -2231,7 +2235,7 @@ void RasterizerStorageGLES2::mesh_add_surface(RID p_mesh, uint32_t p_format, VS: } mesh->surfaces.push_back(surface); - mesh->instance_change_notify(true, false); + mesh->instance_change_notify(true, true); info.vertex_mem += surface->total_data_size; } @@ -4200,7 +4204,12 @@ void RasterizerStorageGLES2::_render_target_allocate(RenderTarget *rt) { glGenTextures(1, &rt->color); glBindTexture(GL_TEXTURE_2D, rt->color); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, rt->width, rt->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + + if (rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) { + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, rt->width, rt->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + } else { + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, rt->width, rt->height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); + } if (texture->flags & VS::TEXTURE_FLAG_FILTER) { @@ -4218,20 +4227,26 @@ void RasterizerStorageGLES2::_render_target_allocate(RenderTarget *rt) { // depth - glGenRenderbuffers(1, &rt->depth); - glBindRenderbuffer(GL_RENDERBUFFER, rt->depth); + glGenTextures(1, &rt->depth); + glBindTexture(GL_TEXTURE_2D, rt->depth); + #ifdef JAVASCRIPT_ENABLED - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, rt->width, rt->height); + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, rt->width, rt->height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL); #else - glRenderbufferStorage(GL_RENDERBUFFER, _DEPTH_COMPONENT24_OES, rt->width, rt->height); + glTexImage2D(GL_TEXTURE_2D, 0, _DEPTH_COMPONENT24_OES, rt->width, rt->height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL); #endif - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, rt->depth, 0); GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); if (status != GL_FRAMEBUFFER_COMPLETE) { - glDeleteRenderbuffers(1, &rt->fbo); + glDeleteFramebuffers(1, &rt->fbo); glDeleteTextures(1, &rt->depth); glDeleteTextures(1, &rt->color); rt->fbo = 0; @@ -4264,13 +4279,15 @@ void RasterizerStorageGLES2::_render_target_allocate(RenderTarget *rt) { // copy texscreen buffers if (!(rt->flags[RasterizerStorage::RENDER_TARGET_NO_SAMPLING])) { - int w = rt->width; - int h = rt->height; - glGenTextures(1, &rt->copy_screen_effect.color); glBindTexture(GL_TEXTURE_2D, rt->copy_screen_effect.color); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + if (rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) { + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, rt->width, rt->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + } else { + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, rt->width, rt->height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); + } + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); @@ -4283,7 +4300,7 @@ void RasterizerStorageGLES2::_render_target_allocate(RenderTarget *rt) { glClearColor(0, 0, 0, 0); glClear(GL_COLOR_BUFFER_BIT); - GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + status = glCheckFramebufferStatus(GL_FRAMEBUFFER); if (status != GL_FRAMEBUFFER_COMPLETE) { _render_target_clear(rt); ERR_FAIL_COND(status != GL_FRAMEBUFFER_COMPLETE); @@ -4302,7 +4319,7 @@ void RasterizerStorageGLES2::_render_target_clear(RenderTarget *rt) { } if (rt->depth) { - glDeleteRenderbuffers(1, &rt->depth); + glDeleteTextures(1, &rt->depth); rt->depth = 0; } @@ -4313,7 +4330,6 @@ void RasterizerStorageGLES2::_render_target_clear(RenderTarget *rt) { tex->height = 0; tex->active = false; - // TODO hardcoded texscreen copy effect if (rt->copy_screen_effect.color) { glDeleteFramebuffers(1, &rt->copy_screen_effect.fbo); rt->copy_screen_effect.fbo = 0; diff --git a/drivers/gles2/rasterizer_storage_gles2.h b/drivers/gles2/rasterizer_storage_gles2.h index ba48ddd185..a0fa2aacc5 100644 --- a/drivers/gles2/rasterizer_storage_gles2.h +++ b/drivers/gles2/rasterizer_storage_gles2.h @@ -31,7 +31,7 @@ #ifndef RASTERIZERSTORAGEGLES2_H #define RASTERIZERSTORAGEGLES2_H -#include "core/dvector.h" +#include "core/pool_vector.h" #include "core/self_list.h" #include "servers/visual/rasterizer.h" #include "servers/visual/shader_language.h" diff --git a/drivers/gles2/shader_compiler_gles2.cpp b/drivers/gles2/shader_compiler_gles2.cpp index fa1242ceed..fdd905458b 100644 --- a/drivers/gles2/shader_compiler_gles2.cpp +++ b/drivers/gles2/shader_compiler_gles2.cpp @@ -81,7 +81,7 @@ static String _opstr(SL::Operator p_op) { static String _mkid(const String &p_id) { String id = "m_" + p_id; - return id.replace("__", "_dus_"); //doubleunderscore is reserverd in glsl + return id.replace("__", "_dus_"); //doubleunderscore is reserved in glsl } static String f2sp0(float p_float) { @@ -318,7 +318,7 @@ String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, Gener uniform_code += "uniform "; - uniform_code += _prestr(E->get().precission); + uniform_code += _prestr(E->get().precision); uniform_code += _typestr(E->get().type); uniform_code += " "; uniform_code += _mkid(E->key()); @@ -344,7 +344,7 @@ String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, Gener StringBuffer<> varying_code; varying_code += "varying "; - varying_code += _prestr(E->get().precission); + varying_code += _prestr(E->get().precision); varying_code += _typestr(E->get().type); varying_code += " "; varying_code += _mkid(E->key()); @@ -859,7 +859,7 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() { actions[VS::SHADER_SPATIAL].renames["INSTANCE_CUSTOM"] = "instance_custom"; actions[VS::SHADER_SPATIAL].renames["SCREEN_UV"] = "screen_uv"; actions[VS::SHADER_SPATIAL].renames["SCREEN_TEXTURE"] = "screen_texture"; - actions[VS::SHADER_SPATIAL].renames["DEPTH_TEXTURE"] = "depth_buffer"; + actions[VS::SHADER_SPATIAL].renames["DEPTH_TEXTURE"] = "depth_texture"; // Defined in GLES3, but not available in GLES2 //actions[VS::SHADER_SPATIAL].renames["DEPTH"] = "gl_FragDepth"; actions[VS::SHADER_SPATIAL].renames["ALPHA_SCISSOR"] = "alpha_scissor"; @@ -895,6 +895,7 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() { actions[VS::SHADER_SPATIAL].usage_defines["SSS_STRENGTH"] = "#define ENABLE_SSS\n"; actions[VS::SHADER_SPATIAL].usage_defines["TRANSMISSION"] = "#define TRANSMISSION_USED\n"; actions[VS::SHADER_SPATIAL].usage_defines["SCREEN_TEXTURE"] = "#define SCREEN_TEXTURE_USED\n"; + actions[VS::SHADER_SPATIAL].usage_defines["DEPTH_TEXTURE"] = "#define DEPTH_TEXTURE_USED\n"; actions[VS::SHADER_SPATIAL].usage_defines["SCREEN_UV"] = "#define SCREEN_UV_USED\n"; actions[VS::SHADER_SPATIAL].usage_defines["DIFFUSE_LIGHT"] = "#define USE_LIGHT_SHADER_CODE\n"; diff --git a/drivers/gles2/shader_gles2.cpp b/drivers/gles2/shader_gles2.cpp index 5e259a01f0..012d1538b6 100644 --- a/drivers/gles2/shader_gles2.cpp +++ b/drivers/gles2/shader_gles2.cpp @@ -199,7 +199,7 @@ static void _display_error_with_code(const String &p_error, const Vector<const c static String _mkid(const String &p_id) { String id = "m_" + p_id; - return id.replace("__", "_dus_"); //doubleunderscore is reserverd in glsl + return id.replace("__", "_dus_"); //doubleunderscore is reserved in glsl } ShaderGLES2::Version *ShaderGLES2::get_current_version() { diff --git a/drivers/gles2/shaders/canvas.glsl b/drivers/gles2/shaders/canvas.glsl index c4a8c8b990..e74c7d7166 100644 --- a/drivers/gles2/shaders/canvas.glsl +++ b/drivers/gles2/shaders/canvas.glsl @@ -316,9 +316,35 @@ FRAGMENT_SHADER_GLOBALS /* clang-format on */ +void light_compute( + inout vec4 light, + inout vec2 light_vec, + inout float light_height, + inout vec4 light_color, + vec2 light_uv, + inout vec4 shadow_color, + vec3 normal, + vec2 uv, +#if defined(SCREEN_UV_USED) + vec2 screen_uv, +#endif + vec4 color) { + +#if defined(USE_LIGHT_SHADER_CODE) + + /* clang-format off */ + +LIGHT_SHADER_CODE + + /* clang-format on */ + +#endif +} + void main() { vec4 color = color_interp; + vec2 uv = uv_interp; #if !defined(COLOR_USED) //default behavior, texture by color @@ -414,7 +440,10 @@ FRAGMENT_SHADER_CODE color *= light; #ifdef USE_SHADOWS - light_vec = light_uv_interp.zw; //for shadows + // Reset light_vec to compute shadows, the shadow map is created from the light origin, so it only + // makes sense to compute shadows from there. + light_vec = light_uv_interp.zw; + float angle_to_light = -atan(light_vec.x, light_vec.y); float PI = 3.14159265358979323846264; /*int i = int(mod(floor((angle_to_light+7.0*PI/6.0)/(4.0*PI/6.0))+1.0, 3.0)); // +1 pq os indices estao em ordem 2,0,1 nos arrays diff --git a/drivers/gles2/shaders/scene.glsl b/drivers/gles2/shaders/scene.glsl index 6c3d3baccd..6f86152598 100644 --- a/drivers/gles2/shaders/scene.glsl +++ b/drivers/gles2/shaders/scene.glsl @@ -158,6 +158,7 @@ varying highp vec3 specular_interp; // general for all lights uniform highp vec4 light_color; +uniform highp vec4 shadow_color; uniform highp float light_specular; // directional @@ -723,6 +724,9 @@ uniform vec2 screen_pixel_size; #if defined(SCREEN_TEXTURE_USED) uniform highp sampler2D screen_texture; //texunit:-4 #endif +#if defined(DEPTH_TEXTURE_USED) +uniform highp sampler2D depth_texture; //texunit:-4 +#endif #ifdef USE_REFLECTION_PROBE1 @@ -912,6 +916,7 @@ uniform highp vec3 light_direction; //may be used by fog, so leave here //done in fragment // general for all lights uniform highp vec4 light_color; +uniform highp vec4 shadow_color; uniform highp float light_specular; // directional @@ -1680,7 +1685,7 @@ FRAGMENT_SHADER_CODE float shadow = sample_shadow(light_shadow_atlas, splane); - light_att *= shadow; + light_att *= mix(shadow_color.rgb, vec3(1.0), shadow); } #endif @@ -1757,7 +1762,7 @@ FRAGMENT_SHADER_CODE shadow_att = mix(shadow_att, shadow_att2, pssm_blend); } #endif - light_att *= shadow_att; + light_att *= mix(shadow_color.rgb, vec3(1.0), shadow_att); } #endif //LIGHT_USE_PSSM4 @@ -1798,7 +1803,7 @@ FRAGMENT_SHADER_CODE shadow_att = mix(shadow_att, shadow_att2, pssm_blend); } #endif - light_att *= shadow_att; + light_att *= mix(shadow_color.rgb, vec3(1.0), shadow_att); } #endif //LIGHT_USE_PSSM2 @@ -1905,7 +1910,7 @@ FRAGMENT_SHADER_CODE } #endif - light_att *= shadow; + light_att *= mix(shadow_color.rgb, vec3(1.0), shadow); } } #endif //use vertex lighting @@ -1953,7 +1958,7 @@ FRAGMENT_SHADER_CODE highp vec4 splane = shadow_coord; float shadow = sample_shadow(light_shadow_atlas, splane); - light_att *= shadow; + light_att *= mix(shadow_color.rgb, vec3(1.0), shadow); } #endif @@ -2049,7 +2054,12 @@ FRAGMENT_SHADER_CODE #if defined(USE_VERTEX_LIGHTING) +#if defined(BASE_PASS) gl_FragColor.rgb = mix(gl_FragColor.rgb, fog_interp.rgb, fog_interp.a); +#else + gl_FragColor.rgb *= (1.0 - fog_interp.a); +#endif // BASE_PASS + #else //pixel based fog float fog_amount = 0.0; @@ -2083,7 +2093,11 @@ FRAGMENT_SHADER_CODE } #endif +#if defined(BASE_PASS) gl_FragColor.rgb = mix(gl_FragColor.rgb, fog_color, fog_amount); +#else + gl_FragColor.rgb *= (1.0 - fog_amount); +#endif // BASE_PASS #endif //use vertex lit diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp index b8f0965af8..227445ae5b 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.cpp +++ b/drivers/gles3/rasterizer_canvas_gles3.cpp @@ -581,10 +581,10 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur #ifdef GLES_OVER_GL if (line->antialiased) { glEnable(GL_LINE_SMOOTH); - for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { Vector2 vertsl[2] = { - verts[i], - verts[(i + 1) % 4], + verts[j], + verts[(j + 1) % 4], }; _draw_gui_primitive(2, vertsl, NULL, NULL); } @@ -782,8 +782,8 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur } if (primitive->colors.size() == 1 && primitive->points.size() > 1) { - Color c = primitive->colors[0]; - glVertexAttrib4f(VS::ARRAY_COLOR, c.r, c.g, c.b, c.a); + Color col = primitive->colors[0]; + glVertexAttrib4f(VS::ARRAY_COLOR, col.r, col.g, col.b, col.a); } else if (primitive->colors.empty()) { glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1); @@ -1035,8 +1035,6 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, amount); } else { //split - - int stride = sizeof(float) * 4 * 6; int split = int(Math::ceil(particles->phase * particles->amount)); if (amount - split > 0) { @@ -1099,12 +1097,12 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur points[numpoints] = circle->pos; int indices[numpoints * 3]; - for (int i = 0; i < numpoints; i++) { + for (int j = 0; j < numpoints; j++) { - points[i] = circle->pos + Vector2(Math::sin(i * Math_PI * 2.0 / numpoints), Math::cos(i * Math_PI * 2.0 / numpoints)) * circle->radius; - indices[i * 3 + 0] = i; - indices[i * 3 + 1] = (i + 1) % numpoints; - indices[i * 3 + 2] = numpoints; + points[j] = circle->pos + Vector2(Math::sin(j * Math_PI * 2.0 / numpoints), Math::cos(j * Math_PI * 2.0 / numpoints)) * circle->radius; + indices[j * 3 + 0] = j; + indices[j * 3 + 1] = (j + 1) % numpoints; + indices[j * 3 + 2] = numpoints; } _bind_canvas_texture(RID(), RID()); @@ -1322,6 +1320,8 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list, int p_z, cons glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 1); glBindTexture(GL_TEXTURE_2D, skeleton->texture); state.using_skeleton = true; + state.canvas_shader.set_uniform(CanvasShaderGLES3::SKELETON_TRANSFORM, state.skeleton_transform); + state.canvas_shader.set_uniform(CanvasShaderGLES3::SKELETON_TRANSFORM_INVERSE, state.skeleton_transform_inverse); } else { state.using_skeleton = false; } @@ -1704,6 +1704,8 @@ void RasterizerCanvasGLES3::canvas_debug_viewport_shadows(Light *p_lights_with_s light = light->shadows_next_ptr; } + + canvas_end(); } void RasterizerCanvasGLES3::canvas_light_shadow_buffer_update(RID p_buffer, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders, CameraMatrix *p_xform_cache) { diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 966466d9bc..4cf9054bf6 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -2343,9 +2343,13 @@ void RasterizerSceneGLES3::_add_geometry_with_material(RasterizerStorageGLES3::G state.used_screen_texture = true; } + if (p_material->shader->spatial.uses_depth_texture) { + state.used_depth_texture = true; + } + if (p_depth_pass) { - if (has_blend_alpha || p_material->shader->spatial.uses_depth_texture || (has_base_alpha && p_material->shader->spatial.depth_draw_mode != RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS)) + if (has_blend_alpha || p_material->shader->spatial.uses_depth_texture || (has_base_alpha && p_material->shader->spatial.depth_draw_mode != RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS) || p_material->shader->spatial.depth_draw_mode == RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_NEVER || p_material->shader->spatial.no_depth_test) return; //bye if (!p_material->shader->spatial.uses_alpha_scissor && !p_material->shader->spatial.writes_modelview_or_projection && !p_material->shader->spatial.uses_vertex && !p_material->shader->spatial.uses_discard && p_material->shader->spatial.depth_draw_mode != RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS) { @@ -3114,7 +3118,7 @@ void RasterizerSceneGLES3::_copy_screen(bool p_invalidate_color, bool p_invalida GLenum attachments[2] = { GL_COLOR_ATTACHMENT0, - GL_DEPTH_STENCIL_ATTACHMENT + GL_DEPTH_ATTACHMENT }; glInvalidateFramebuffer(GL_FRAMEBUFFER, p_invalidate_depth ? 2 : 1, attachments); @@ -3159,6 +3163,7 @@ void RasterizerSceneGLES3::_fill_render_list(InstanceBase **p_cull_result, int p current_material_index = 0; state.used_sss = false; state.used_screen_texture = false; + state.used_depth_texture = false; //fill list for (int i = 0; i < p_cull_count; i++) { @@ -3173,10 +3178,10 @@ void RasterizerSceneGLES3::_fill_render_list(InstanceBase **p_cull_result, int p int ssize = mesh->surfaces.size(); - for (int i = 0; i < ssize; i++) { + for (int j = 0; j < ssize; j++) { - int mat_idx = inst->materials[i].is_valid() ? i : -1; - RasterizerStorageGLES3::Surface *s = mesh->surfaces[i]; + int mat_idx = inst->materials[j].is_valid() ? j : -1; + RasterizerStorageGLES3::Surface *s = mesh->surfaces[j]; _add_geometry(s, inst, NULL, mat_idx, p_depth_pass, p_shadow_pass); } @@ -3197,9 +3202,9 @@ void RasterizerSceneGLES3::_fill_render_list(InstanceBase **p_cull_result, int p int ssize = mesh->surfaces.size(); - for (int i = 0; i < ssize; i++) { + for (int j = 0; j < ssize; j++) { - RasterizerStorageGLES3::Surface *s = mesh->surfaces[i]; + RasterizerStorageGLES3::Surface *s = mesh->surfaces[j]; _add_geometry(s, inst, multi_mesh, -1, p_depth_pass, p_shadow_pass); } @@ -3217,9 +3222,9 @@ void RasterizerSceneGLES3::_fill_render_list(InstanceBase **p_cull_result, int p RasterizerStorageGLES3::Particles *particles = storage->particles_owner.getptr(inst->base); ERR_CONTINUE(!particles); - for (int i = 0; i < particles->draw_passes.size(); i++) { + for (int j = 0; j < particles->draw_passes.size(); j++) { - RID pmesh = particles->draw_passes[i]; + RID pmesh = particles->draw_passes[j]; if (!pmesh.is_valid()) continue; RasterizerStorageGLES3::Mesh *mesh = storage->mesh_owner.get(pmesh); @@ -3228,9 +3233,9 @@ void RasterizerSceneGLES3::_fill_render_list(InstanceBase **p_cull_result, int p int ssize = mesh->surfaces.size(); - for (int j = 0; j < ssize; j++) { + for (int k = 0; k < ssize; k++) { - RasterizerStorageGLES3::Surface *s = mesh->surfaces[j]; + RasterizerStorageGLES3::Surface *s = mesh->surfaces[k]; _add_geometry(s, inst, particles, -1, p_depth_pass, p_shadow_pass); } } @@ -3281,6 +3286,16 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env, const CameraMatrix &p_ glDisable(GL_CULL_FACE); glDisable(GL_BLEND); + if (!state.used_depth_prepass_and_resolved) { + //resolve depth buffer + glBindFramebuffer(GL_READ_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo); + glReadBuffer(GL_COLOR_ATTACHMENT0); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, storage->frame.current_rt->fbo); + glBlitFramebuffer(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, 0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, GL_DEPTH_BUFFER_BIT, GL_NEAREST); + glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + } + if (env->ssao_enabled || env->ssr_enabled) { //copy normal and roughness to effect buffer @@ -4133,6 +4148,7 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const glDepthFunc(GL_LEQUAL); state.used_contact_shadows = false; + state.used_depth_prepass_and_resolved = false; for (int i = 0; i < p_light_cull_count; i++) { @@ -4158,7 +4174,7 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const glColorMask(0, 0, 0, 0); glClearDepth(1.0f); - glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + glClear(GL_DEPTH_BUFFER_BIT); render_list.clear(); _fill_render_list(p_cull_result, p_cull_count, true, false); @@ -4169,7 +4185,7 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const glColorMask(1, 1, 1, 1); - if (state.used_contact_shadows) { + if (state.used_contact_shadows || state.used_depth_texture) { glBindFramebuffer(GL_READ_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo); glReadBuffer(GL_COLOR_ATTACHMENT0); @@ -4180,13 +4196,14 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const //bind depth for read glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 8); glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->depth); + state.used_depth_prepass_and_resolved = true; } fb_cleared = true; render_pass++; - state.using_contact_shadows = true; + state.used_depth_prepass = true; } else { - state.using_contact_shadows = false; + state.used_depth_prepass = false; } _setup_lights(p_light_cull_result, p_light_cull_count, p_cam_transform.affine_inverse(), p_cam_projection, p_shadow_atlas); @@ -4283,7 +4300,8 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const } if (!fb_cleared) { - glClearBufferfi(GL_DEPTH_STENCIL, 0, 1.0, 0); + glClearDepth(1.0f); + glClear(GL_DEPTH_BUFFER_BIT); } Color clear_color(0, 0, 0, 0); @@ -4433,6 +4451,7 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const //state.scene_shader.set_conditional( SceneShaderGLES3::USE_FOG,false); if (use_mrt) { + _render_mrts(env, p_cam_projection); } else { //FIXME: check that this is possible to use @@ -4557,7 +4576,7 @@ void RasterizerSceneGLES3::render_shadow(RID p_light, RID p_shadow_atlas, int p_ float bias = 0; float normal_bias = 0; - state.using_contact_shadows = false; + state.used_depth_prepass = false; CameraMatrix light_projection; Transform light_transform; @@ -5054,7 +5073,7 @@ void RasterizerSceneGLES3::initialize() { { //reflection cubemaps int max_reflection_cubemap_sampler_size = 512; - int cube_size = max_reflection_cubemap_sampler_size; + int rcube_size = max_reflection_cubemap_sampler_size; glActiveTexture(GL_TEXTURE0); @@ -5064,10 +5083,10 @@ void RasterizerSceneGLES3::initialize() { GLenum format = GL_RGBA; GLenum type = use_float ? GL_HALF_FLOAT : GL_UNSIGNED_INT_2_10_10_10_REV; - while (cube_size >= 32) { + while (rcube_size >= 32) { ReflectionCubeMap cube; - cube.size = cube_size; + cube.size = rcube_size; glGenTextures(1, &cube.depth); glBindTexture(GL_TEXTURE_2D, cube.depth); @@ -5106,7 +5125,7 @@ void RasterizerSceneGLES3::initialize() { reflection_cubemaps.push_back(cube); - cube_size >>= 1; + rcube_size >>= 1; } } @@ -5162,12 +5181,15 @@ void RasterizerSceneGLES3::initialize() { glGenTextures(1, &e.color); glBindTexture(GL_TEXTURE_2D, e.color); -#ifdef IPHONE_ENABLED - ///@TODO ugly hack to get around iOS not supporting 32bit single channel floating point textures... - glTexImage2D(GL_TEXTURE_2D, 0, GL_R16F, max_exposure_shrink_size, max_exposure_shrink_size, 0, GL_RED, GL_FLOAT, NULL); -#else - glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, max_exposure_shrink_size, max_exposure_shrink_size, 0, GL_RED, GL_FLOAT, NULL); -#endif + + if (storage->config.framebuffer_float_supported) { + glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, max_exposure_shrink_size, max_exposure_shrink_size, 0, GL_RED, GL_FLOAT, NULL); + } else if (storage->config.framebuffer_half_float_supported) { + glTexImage2D(GL_TEXTURE_2D, 0, GL_R16F, max_exposure_shrink_size, max_exposure_shrink_size, 0, GL_RED, GL_HALF_FLOAT, NULL); + } else { + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB10_A2, max_exposure_shrink_size, max_exposure_shrink_size, 0, GL_RED, GL_UNSIGNED_INT_2_10_10_10_REV, NULL); + } + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, e.color, 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index 325617745a..3ac5ade721 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -204,7 +204,9 @@ public: bool cull_disabled; bool used_sss; bool used_screen_texture; - bool using_contact_shadows; + bool used_depth_texture; + bool used_depth_prepass; + bool used_depth_prepass_and_resolved; VS::ViewportDebugDraw debug_draw; } state; diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index 4ef7db8ea9..99e594d242 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -101,6 +101,10 @@ #define _EXT_COMPRESSED_RGB_BPTC_SIGNED_FLOAT 0x8E8E #define _EXT_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT 0x8E8F +#ifndef GLES_OVER_GL +#define glClearDepth glClearDepthf +#endif + #ifdef __EMSCRIPTEN__ #include <emscripten/emscripten.h> @@ -1539,7 +1543,7 @@ RID RasterizerStorageGLES3::texture_create_radiance_cubemap(RID p_source, int p_ ERR_FAIL_COND_V(!texture, RID()); ERR_FAIL_COND_V(texture->type != VS::TEXTURE_TYPE_CUBEMAP, RID()); - bool use_float = config.hdr_supported; + bool use_float = config.framebuffer_half_float_supported; if (p_resolution < 0) { p_resolution = texture->width; @@ -1787,7 +1791,7 @@ void RasterizerStorageGLES3::sky_set_texture(RID p_sky, RID p_panorama, int p_ra int array_level = 6; - bool use_float = config.hdr_supported; + bool use_float = config.framebuffer_half_float_supported; GLenum internal_format = use_float ? GL_RGBA16F : GL_RGB10_A2; GLenum format = GL_RGBA; @@ -1899,7 +1903,7 @@ void RasterizerStorageGLES3::sky_set_texture(RID p_sky, RID p_panorama, int p_ra int mm_level = mipmaps; - bool use_float = config.hdr_supported; + bool use_float = config.framebuffer_half_float_supported; GLenum internal_format = use_float ? GL_RGBA16F : GL_RGB10_A2; GLenum format = GL_RGBA; @@ -3616,7 +3620,7 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh, uint32_t p_format, VS: } mesh->surfaces.push_back(surface); - mesh->instance_change_notify(true, false); + mesh->instance_change_notify(true, true); info.vertex_mem += surface->total_data_size; } @@ -6045,9 +6049,9 @@ void RasterizerStorageGLES3::particles_set_amount(RID p_particles, int p_amount) glBindBuffer(GL_ARRAY_BUFFER, particles->particle_buffers[i]); glBufferData(GL_ARRAY_BUFFER, floats * sizeof(float), data, GL_STATIC_DRAW); - for (int i = 0; i < 6; i++) { - glEnableVertexAttribArray(i); - glVertexAttribPointer(i, 4, GL_FLOAT, GL_FALSE, sizeof(float) * 4 * 6, ((uint8_t *)0) + (i * 16)); + for (int j = 0; j < 6; j++) { + glEnableVertexAttribArray(j); + glVertexAttribPointer(j, 4, GL_FLOAT, GL_FALSE, sizeof(float) * 4 * 6, ((uint8_t *)0) + (j * 16)); } } @@ -6800,7 +6804,7 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) { GLuint color_type; Image::Format image_format; - bool hdr = rt->flags[RENDER_TARGET_HDR] && config.hdr_supported; + bool hdr = rt->flags[RENDER_TARGET_HDR] && config.framebuffer_half_float_supported; //hdr = false; if (!hdr || rt->flags[RENDER_TARGET_NO_3D]) { @@ -6836,8 +6840,9 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) { glGenTextures(1, &rt->depth); glBindTexture(GL_TEXTURE_2D, rt->depth); - glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, rt->width, rt->height, 0, - GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL); + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, rt->width, rt->height, 0, + GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); @@ -6904,9 +6909,9 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) { glGenRenderbuffers(1, &rt->buffers.depth); glBindRenderbuffer(GL_RENDERBUFFER, rt->buffers.depth); if (msaa == 0) - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, rt->width, rt->height); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, rt->width, rt->height); else - glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa, GL_DEPTH24_STENCIL8, rt->width, rt->height); + glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa, GL_DEPTH_COMPONENT24, rt->width, rt->height); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->buffers.depth); @@ -7054,7 +7059,14 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) { glGenTextures(1, &rt->exposure.color); glBindTexture(GL_TEXTURE_2D, rt->exposure.color); - glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, 1, 1, 0, GL_RED, GL_FLOAT, NULL); + if (config.framebuffer_float_supported) { + glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, 1, 1, 0, GL_RED, GL_FLOAT, NULL); + } else if (config.framebuffer_half_float_supported) { + glTexImage2D(GL_TEXTURE_2D, 0, GL_R16F, 1, 1, 0, GL_RED, GL_HALF_FLOAT, NULL); + } else { + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB10_A2, 1, 1, 0, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, NULL); + } + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->exposure.color, 0); status = glCheckFramebufferStatus(GL_FRAMEBUFFER); @@ -7139,7 +7151,8 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) { glViewport(0, 0, rt->effects.mip_maps[i].sizes[j].width, rt->effects.mip_maps[i].sizes[j].height); glClearBufferfv(GL_COLOR, 0, zero); if (used_depth) { - glClearBufferfi(GL_DEPTH_STENCIL, 0, 1.0, 0); + glClearDepth(1.0); + glClear(GL_DEPTH_BUFFER_BIT); } } @@ -7809,17 +7822,21 @@ void RasterizerStorageGLES3::initialize() { config.latc_supported = config.extensions.has("GL_EXT_texture_compression_latc"); config.bptc_supported = config.extensions.has("GL_ARB_texture_compression_bptc"); #ifdef GLES_OVER_GL - config.hdr_supported = true; config.etc2_supported = false; config.s3tc_supported = true; config.rgtc_supported = true; //RGTC - core since OpenGL version 3.0 config.texture_float_linear_supported = true; + config.framebuffer_float_supported = true; + config.framebuffer_half_float_supported = true; + #else config.etc2_supported = true; - config.hdr_supported = false; config.s3tc_supported = config.extensions.has("GL_EXT_texture_compression_dxt1") || config.extensions.has("GL_EXT_texture_compression_s3tc") || config.extensions.has("WEBGL_compressed_texture_s3tc"); config.rgtc_supported = config.extensions.has("GL_EXT_texture_compression_rgtc") || config.extensions.has("GL_ARB_texture_compression_rgtc") || config.extensions.has("EXT_texture_compression_rgtc"); config.texture_float_linear_supported = config.extensions.has("GL_OES_texture_float_linear"); + config.framebuffer_float_supported = config.extensions.has("GL_EXT_color_buffer_float"); + config.framebuffer_half_float_supported = config.extensions.has("GL_EXT_color_buffer_half_float") || config.framebuffer_float_supported; + #endif config.pvrtc_supported = config.extensions.has("GL_IMG_texture_compression_pvrtc"); @@ -7912,11 +7929,7 @@ void RasterizerStorageGLES3::initialize() { glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &config.max_texture_image_units); glGetIntegerv(GL_MAX_TEXTURE_SIZE, &config.max_texture_size); -#ifdef GLES_OVER_GL - config.use_rgba_2d_shadows = false; -#else - config.use_rgba_2d_shadows = true; -#endif + config.use_rgba_2d_shadows = config.framebuffer_float_supported; //generic quadie for copying diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index 88897e1e07..d1e02e25d6 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -82,11 +82,11 @@ public: bool etc2_supported; bool pvrtc_supported; - bool hdr_supported; - bool srgb_decode_supported; bool texture_float_linear_supported; + bool framebuffer_float_supported; + bool framebuffer_half_float_supported; bool use_rgba_2d_shadows; diff --git a/drivers/gles3/shader_compiler_gles3.cpp b/drivers/gles3/shader_compiler_gles3.cpp index 4d6f37e093..ad26294527 100644 --- a/drivers/gles3/shader_compiler_gles3.cpp +++ b/drivers/gles3/shader_compiler_gles3.cpp @@ -167,7 +167,7 @@ static String _opstr(SL::Operator p_op) { static String _mkid(const String &p_id) { String id = "m_" + p_id; - return id.replace("__", "_dus_"); //doubleunderscore is reserverd in glsl + return id.replace("__", "_dus_"); //doubleunderscore is reserved in glsl } static String f2sp0(float p_float) { @@ -373,7 +373,7 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener ucode = "uniform "; } - ucode += _prestr(E->get().precission); + ucode += _prestr(E->get().precision); ucode += _typestr(E->get().type); ucode += " " + _mkid(E->key()); ucode += ";\n"; @@ -464,7 +464,7 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener String vcode; String interp_mode = _interpstr(E->get().interpolation); - vcode += _prestr(E->get().precission); + vcode += _prestr(E->get().precision); vcode += _typestr(E->get().type); vcode += " " + _mkid(E->key()); vcode += ";\n"; diff --git a/drivers/gles3/shaders/canvas.glsl b/drivers/gles3/shaders/canvas.glsl index 974eff86f3..88368516c1 100644 --- a/drivers/gles3/shaders/canvas.glsl +++ b/drivers/gles3/shaders/canvas.glsl @@ -549,7 +549,10 @@ FRAGMENT_SHADER_CODE color *= light; #ifdef USE_SHADOWS - light_vec = light_uv_interp.zw; //for shadows + // Reset light_vec to compute shadows, the shadow map is created from the light origin, so it only + // makes sense to compute shadows from there. + light_vec = light_uv_interp.zw; + float angle_to_light = -atan(light_vec.x, light_vec.y); float PI = 3.14159265358979323846264; /*int i = int(mod(floor((angle_to_light+7.0*PI/6.0)/(4.0*PI/6.0))+1.0, 3.0)); // +1 pq os indices estao em ordem 2,0,1 nos arrays diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index 1a8ad5e1ef..125faa4eac 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -44,7 +44,7 @@ layout(location = 5) in vec2 uv2_attrib; #ifdef USE_SKELETON layout(location = 6) in uvec4 bone_indices; // attrib:6 -layout(location = 7) in vec4 bone_weights; // attrib:7 +layout(location = 7) in highp vec4 bone_weights; // attrib:7 #endif #ifdef USE_INSTANCING @@ -314,7 +314,7 @@ void main() { highp vec4 vertex = vertex_attrib; // vec4(vertex_attrib.xyz * data_attrib.x,1.0); - mat4 world_matrix = world_transform; + highp mat4 world_matrix = world_transform; #ifdef USE_INSTANCING @@ -395,44 +395,46 @@ void main() { ivec4 bone_indicesi = ivec4(bone_indices); // cast to signed int ivec2 tex_ofs = ivec2(bone_indicesi.x % 256, (bone_indicesi.x / 256) * 3); - highp mat3x4 m; - m = mat3x4( + highp mat4 m; + m = mat4( texelFetch(skeleton_texture, tex_ofs, 0), texelFetch(skeleton_texture, tex_ofs + ivec2(0, 1), 0), - texelFetch(skeleton_texture, tex_ofs + ivec2(0, 2), 0)) * + texelFetch(skeleton_texture, tex_ofs + ivec2(0, 2), 0), + vec4(0.0,0.0,0.0,1.0)) * bone_weights.x; tex_ofs = ivec2(bone_indicesi.y % 256, (bone_indicesi.y / 256) * 3); - m += mat3x4( + m += mat4( texelFetch(skeleton_texture, tex_ofs, 0), texelFetch(skeleton_texture, tex_ofs + ivec2(0, 1), 0), - texelFetch(skeleton_texture, tex_ofs + ivec2(0, 2), 0)) * + texelFetch(skeleton_texture, tex_ofs + ivec2(0, 2), 0), + vec4(0.0,0.0,0.0,1.0)) * bone_weights.y; tex_ofs = ivec2(bone_indicesi.z % 256, (bone_indicesi.z / 256) * 3); - m += mat3x4( + m += mat4( texelFetch(skeleton_texture, tex_ofs, 0), texelFetch(skeleton_texture, tex_ofs + ivec2(0, 1), 0), - texelFetch(skeleton_texture, tex_ofs + ivec2(0, 2), 0)) * + texelFetch(skeleton_texture, tex_ofs + ivec2(0, 2), 0), + vec4(0.0,0.0,0.0,1.0)) * bone_weights.z; tex_ofs = ivec2(bone_indicesi.w % 256, (bone_indicesi.w / 256) * 3); - m += mat3x4( + m += mat4( texelFetch(skeleton_texture, tex_ofs, 0), texelFetch(skeleton_texture, tex_ofs + ivec2(0, 1), 0), - texelFetch(skeleton_texture, tex_ofs + ivec2(0, 2), 0)) * + texelFetch(skeleton_texture, tex_ofs + ivec2(0, 2), 0), + vec4(0.0,0.0,0.0,1.0)) * bone_weights.w; - mat4 bone_matrix = transpose(mat4(m[0], m[1], m[2], vec4(0.0, 0.0, 0.0, 1.0))); - - world_matrix = bone_matrix * world_matrix; + world_matrix = transpose(m) * world_matrix; } #endif - mat4 modelview = camera_inverse_matrix * world_matrix; + highp mat4 modelview = camera_inverse_matrix * world_matrix; { /* clang-format off */ diff --git a/drivers/gles3/shaders/tonemap.glsl b/drivers/gles3/shaders/tonemap.glsl index 80ad003c80..626968bc05 100644 --- a/drivers/gles3/shaders/tonemap.glsl +++ b/drivers/gles3/shaders/tonemap.glsl @@ -124,7 +124,7 @@ vec4 texture2D_bicubic(sampler2D tex, vec2 uv, int p_lod) { #endif vec3 tonemap_filmic(vec3 color, float white) { - // exposure bias: input scale (color *= bias, white *= bias) to make the brighness consistent with other tonemappers + // exposure bias: input scale (color *= bias, white *= bias) to make the brightness consistent with other tonemappers // also useful to scale the input to the range that the tonemapper is designed for (some require very high input values) // has no effect on the curve's general shape or visual properties const float exposure_bias = 2.0f; diff --git a/drivers/pulseaudio/audio_driver_pulseaudio.cpp b/drivers/pulseaudio/audio_driver_pulseaudio.cpp index 0d98b7fbc0..aec3d27d69 100644 --- a/drivers/pulseaudio/audio_driver_pulseaudio.cpp +++ b/drivers/pulseaudio/audio_driver_pulseaudio.cpp @@ -420,7 +420,7 @@ void AudioDriverPulseAudio::thread_func(void *p_udata) { pa_operation *pa_op = pa_context_get_server_info(ad->pa_ctx, &AudioDriverPulseAudio::pa_server_info_cb, (void *)ad); if (pa_op) { while (ad->pa_status == 0) { - int ret = pa_mainloop_iterate(ad->pa_ml, 1, NULL); + ret = pa_mainloop_iterate(ad->pa_ml, 1, NULL); if (ret < 0) { ERR_PRINT("pa_mainloop_iterate error"); } diff --git a/drivers/rtaudio/SCsub b/drivers/rtaudio/SCsub deleted file mode 100644 index 285658073c..0000000000 --- a/drivers/rtaudio/SCsub +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env python - -Import('env') - -# Not cloning the env, the includes need to be accessible for platform/ - -# Thirdparty source files -thirdparty_dir = "#thirdparty/rtaudio/" -thirdparty_sources = [ - "RtAudio.cpp", -] -thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources] - -env.Append(CPPPATH=[thirdparty_dir]) - -env_thirdparty = env.Clone() -env_thirdparty.disable_warnings() -env_thirdparty.add_source_files(env.drivers_sources, thirdparty_sources) - -# Driver source files -env.add_source_files(env.drivers_sources, "*.cpp") - -Export('env') diff --git a/drivers/rtaudio/audio_driver_rtaudio.cpp b/drivers/rtaudio/audio_driver_rtaudio.cpp deleted file mode 100644 index e45621d70f..0000000000 --- a/drivers/rtaudio/audio_driver_rtaudio.cpp +++ /dev/null @@ -1,205 +0,0 @@ -/*************************************************************************/ -/* audio_driver_rtaudio.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "audio_driver_rtaudio.h" - -#include "core/os/os.h" -#include "core/project_settings.h" - -#ifdef RTAUDIO_ENABLED - -const char *AudioDriverRtAudio::get_name() const { - -#ifdef OSX_ENABLED - return "RtAudio-OSX"; -#elif defined(UNIX_ENABLED) - return "RtAudio-ALSA"; -#elif defined(WINDOWS_ENABLED) - return "RtAudio-DirectSound"; -#else - return "RtAudio-None"; -#endif -} - -int AudioDriverRtAudio::callback(void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames, double streamTime, RtAudioStreamStatus status, void *userData) { - - if (status) { - if (status & RTAUDIO_INPUT_OVERFLOW) { - WARN_PRINT("RtAudio input overflow!"); - } - if (status & RTAUDIO_OUTPUT_UNDERFLOW) { - WARN_PRINT("RtAudio output underflow!"); - } - } - int32_t *buffer = (int32_t *)outputBuffer; - - AudioDriverRtAudio *self = (AudioDriverRtAudio *)userData; - - if (self->mutex->try_lock() != OK) { - // what should i do.. - for (unsigned int i = 0; i < nBufferFrames; i++) - buffer[i] = 0; - - return 0; - } - - self->audio_server_process(nBufferFrames, buffer); - - self->mutex->unlock(); - - return 0; -} - -Error AudioDriverRtAudio::init() { - - active = false; - mutex = Mutex::create(true); - dac = memnew(RtAudio); - - ERR_EXPLAIN("Cannot initialize RtAudio audio driver: No devices present.") - ERR_FAIL_COND_V(dac->getDeviceCount() < 1, ERR_UNAVAILABLE); - - // FIXME: Adapt to the OutputFormat -> SpeakerMode change - /* - String channels = GLOBAL_DEF_RST("audio/output","stereo"); - - if (channels=="5.1") - output_format=OUTPUT_5_1; - else if (channels=="quad") - output_format=OUTPUT_QUAD; - else if (channels=="mono") - output_format=OUTPUT_MONO; - else - output_format=OUTPUT_STEREO; - */ - - RtAudio::StreamParameters parameters; - parameters.deviceId = dac->getDefaultOutputDevice(); - RtAudio::StreamOptions options; - - // set the desired numberOfBuffers - options.numberOfBuffers = 4; - - parameters.firstChannel = 0; - mix_rate = GLOBAL_DEF_RST("audio/mix_rate", DEFAULT_MIX_RATE); - - int latency = GLOBAL_DEF("audio/output_latency", DEFAULT_OUTPUT_LATENCY); - unsigned int buffer_frames = closest_power_of_2(latency * mix_rate / 1000); - print_verbose("Audio buffer frames: " + itos(buffer_frames) + " calculated latency: " + itos(buffer_frames * 1000 / mix_rate) + "ms"); - - short int tries = 4; - - while (tries > 0) { - switch (speaker_mode) { - case SPEAKER_MODE_STEREO: parameters.nChannels = 2; break; - case SPEAKER_SURROUND_31: parameters.nChannels = 4; break; - case SPEAKER_SURROUND_51: parameters.nChannels = 6; break; - case SPEAKER_SURROUND_71: parameters.nChannels = 8; break; - }; - - try { - dac->openStream(¶meters, NULL, RTAUDIO_SINT32, mix_rate, &buffer_frames, &callback, this, &options); - active = true; - - break; - } catch (RtAudioError) { - // try with less channels - ERR_PRINT("Unable to open audio, retrying with fewer channels..."); - - switch (speaker_mode) { - case SPEAKER_MODE_STEREO: break; // Required to silence unhandled enum value warning. - case SPEAKER_SURROUND_31: speaker_mode = SPEAKER_MODE_STEREO; break; - case SPEAKER_SURROUND_51: speaker_mode = SPEAKER_SURROUND_31; break; - case SPEAKER_SURROUND_71: speaker_mode = SPEAKER_SURROUND_51; break; - } - - tries--; - } - } - - return active ? OK : ERR_UNAVAILABLE; -} - -int AudioDriverRtAudio::get_mix_rate() const { - - return mix_rate; -} - -AudioDriver::SpeakerMode AudioDriverRtAudio::get_speaker_mode() const { - - return speaker_mode; -} - -void AudioDriverRtAudio::start() { - - if (active) - dac->startStream(); -} - -void AudioDriverRtAudio::lock() { - - if (mutex) - mutex->lock(); -} - -void AudioDriverRtAudio::unlock() { - - if (mutex) - mutex->unlock(); -} - -void AudioDriverRtAudio::finish() { - - lock(); - if (active && dac->isStreamOpen()) { - dac->closeStream(); - active = false; - } - unlock(); - - if (mutex) { - memdelete(mutex); - mutex = NULL; - } - if (dac) { - memdelete(dac); - dac = NULL; - } -} - -AudioDriverRtAudio::AudioDriverRtAudio() : - speaker_mode(SPEAKER_MODE_STEREO), - mutex(NULL), - dac(NULL), - mix_rate(DEFAULT_MIX_RATE), - active(false) { -} - -#endif diff --git a/drivers/rtaudio/audio_driver_rtaudio.h b/drivers/rtaudio/audio_driver_rtaudio.h deleted file mode 100644 index ac4eee4947..0000000000 --- a/drivers/rtaudio/audio_driver_rtaudio.h +++ /dev/null @@ -1,65 +0,0 @@ -/*************************************************************************/ -/* audio_driver_rtaudio.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef AUDIO_DRIVER_RTAUDIO_H -#define AUDIO_DRIVER_RTAUDIO_H - -#ifdef RTAUDIO_ENABLED - -#include "servers/audio_server.h" - -#include <RtAudio.h> - -class AudioDriverRtAudio : public AudioDriver { - - static int callback(void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames, - double streamTime, RtAudioStreamStatus status, void *userData); - SpeakerMode speaker_mode; - Mutex *mutex; - RtAudio *dac; - int mix_rate; - bool active; - -public: - virtual const char *get_name() const; - - virtual Error init(); - virtual void start(); - virtual int get_mix_rate() const; - virtual SpeakerMode get_speaker_mode() const; - virtual void lock(); - virtual void unlock(); - virtual void finish(); - - AudioDriverRtAudio(); -}; - -#endif // AUDIO_DRIVER_RTAUDIO_H -#endif diff --git a/drivers/unix/ip_unix.cpp b/drivers/unix/ip_unix.cpp index 824ba7bb8a..b5feaabc32 100644 --- a/drivers/unix/ip_unix.cpp +++ b/drivers/unix/ip_unix.cpp @@ -50,7 +50,7 @@ #define _WIN32_WINNT 0x0501 // Windows XP, disable Vista API #include <iphlpapi.h> #undef _WIN32_WINNT -#define _WIN32_WINNT 0x0600 // Reenable Vista API +#define _WIN32_WINNT 0x0600 // Re-enable Vista API #else #include <iphlpapi.h> #endif // MINGW hack diff --git a/drivers/unix/net_socket_posix.cpp b/drivers/unix/net_socket_posix.cpp index 6910abc64c..2dffa083fe 100644 --- a/drivers/unix/net_socket_posix.cpp +++ b/drivers/unix/net_socket_posix.cpp @@ -543,7 +543,7 @@ void NetSocketPosix::set_blocking_enabled(bool p_enabled) { void NetSocketPosix::set_ipv6_only_enabled(bool p_enabled) { ERR_FAIL_COND(!is_open()); - // This option is only avaiable in IPv6 sockets. + // This option is only available in IPv6 sockets. ERR_FAIL_COND(_ip_type == IP::TYPE_IPV4); int par = p_enabled ? 1 : 0; diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp index e3e2e10e82..e7550903a8 100644 --- a/drivers/unix/os_unix.cpp +++ b/drivers/unix/os_unix.cpp @@ -282,7 +282,7 @@ uint64_t OS_Unix::get_ticks_usec() const { uint64_t longtime = mach_absolute_time() * _clock_scale; #else // Unchecked return. Static analyzers might complain. - // If _setup_clock() succeded, we assume clock_gettime() works. + // If _setup_clock() succeeded, we assume clock_gettime() works. struct timespec tv_now = { 0, 0 }; clock_gettime(GODOT_CLOCK, &tv_now); uint64_t longtime = ((uint64_t)tv_now.tv_nsec / 1000L) + (uint64_t)tv_now.tv_sec * 1000000L; diff --git a/drivers/wasapi/audio_driver_wasapi.cpp b/drivers/wasapi/audio_driver_wasapi.cpp index 38012f8f76..685e821389 100644 --- a/drivers/wasapi/audio_driver_wasapi.cpp +++ b/drivers/wasapi/audio_driver_wasapi.cpp @@ -270,6 +270,7 @@ Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_c } hr = p_device->audio_client->Initialize(AUDCLNT_SHAREMODE_SHARED, streamflags, p_capture ? REFTIMES_PER_SEC : 0, 0, pwfex, NULL); + ERR_EXPLAIN("WASAPI: Initialize failed with error 0x" + String::num_uint64(hr, 16)); ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN); if (p_capture) { diff --git a/drivers/windows/shell_windows.cpp b/drivers/windows/shell_windows.cpp deleted file mode 100644 index 731d16d18d..0000000000 --- a/drivers/windows/shell_windows.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/*************************************************************************/ -/* shell_windows.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifdef WINDOWS_ENABLED - -#ifdef UWP_ENABLED - -// Use Launcher class on windows 8 - -#else - -// -// C++ Implementation: shell_windows -// -// Description: -// -// -// Author: Juan Linietsky <reduzio@gmail.com>, (C) 2008 -// -// Copyright: See COPYING file that comes with this distribution -// -// -#include "shell_windows.h" - -#include <windows.h> - -void ShellWindows::execute(String p_path) { - - ShellExecuteW(NULL, L"open", p_path.c_str(), NULL, NULL, SW_SHOWNORMAL); -} - -ShellWindows::ShellWindows() { -} - -ShellWindows::~ShellWindows() { -} - -#endif - -#endif diff --git a/drivers/windows/shell_windows.h b/drivers/windows/shell_windows.h deleted file mode 100644 index 9e9edd2f62..0000000000 --- a/drivers/windows/shell_windows.h +++ /dev/null @@ -1,52 +0,0 @@ -/*************************************************************************/ -/* shell_windows.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef SHELL_WINDOWS_H -#define SHELL_WINDOWS_H - -#include "core/os/shell.h" - -#ifdef WINDOWS_ENABLED - -/** - @author Juan Linietsky <reduzio@gmail.com> -*/ - -class ShellWindows : public Shell { -public: - virtual void execute(String p_path); - - ShellWindows(); - - ~ShellWindows(); -}; - -#endif -#endif diff --git a/drivers/winmidi/win_midi.cpp b/drivers/winmidi/midi_driver_winmidi.cpp index 26bba34661..65676b629a 100644 --- a/drivers/winmidi/win_midi.cpp +++ b/drivers/winmidi/midi_driver_winmidi.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* win_midi.cpp */ +/* midi_driver_winmidi.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -30,7 +30,7 @@ #ifdef WINMIDI_ENABLED -#include "win_midi.h" +#include "midi_driver_winmidi.h" #include "core/print_string.h" @@ -104,4 +104,4 @@ MIDIDriverWinMidi::~MIDIDriverWinMidi() { close(); } -#endif +#endif // WINMIDI_ENABLED diff --git a/drivers/winmidi/win_midi.h b/drivers/winmidi/midi_driver_winmidi.h index 4341f7ca7e..2eaa70ef8d 100644 --- a/drivers/winmidi/win_midi.h +++ b/drivers/winmidi/midi_driver_winmidi.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* win_midi.h */ +/* midi_driver_winmidi.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -30,8 +30,8 @@ #ifdef WINMIDI_ENABLED -#ifndef WIN_MIDI_H -#define WIN_MIDI_H +#ifndef MIDI_DRIVER_WINMIDI_H +#define MIDI_DRIVER_WINMIDI_H #include "core/os/midi_driver.h" #include "core/vector.h" @@ -57,5 +57,5 @@ public: virtual ~MIDIDriverWinMidi(); }; -#endif -#endif +#endif // MIDI_DRIVER_WINMIDI_H +#endif // WINMIDI_ENABLED diff --git a/editor/animation_bezier_editor.cpp b/editor/animation_bezier_editor.cpp index 565336701a..f6d4a2665c 100644 --- a/editor/animation_bezier_editor.cpp +++ b/editor/animation_bezier_editor.cpp @@ -758,7 +758,7 @@ void AnimationBezierTrackEdit::_gui_input(const Ref<InputEvent> &p_event) { time += 0.001; } - undo_redo->create_action("Add Bezier Point"); + undo_redo->create_action(TTR("Add Bezier Point")); undo_redo->add_do_method(animation.ptr(), "track_insert_key", track, time, new_point); undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_position", track, time); undo_redo->commit_action(); @@ -823,7 +823,7 @@ void AnimationBezierTrackEdit::_gui_input(const Ref<InputEvent> &p_event) { if (moving_handle != 0 && mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { - undo_redo->create_action("Move Bezier Points"); + undo_redo->create_action(TTR("Move Bezier Points")); undo_redo->add_do_method(animation.ptr(), "bezier_track_set_key_in_handle", track, moving_handle_key, moving_handle_left); undo_redo->add_do_method(animation.ptr(), "bezier_track_set_key_out_handle", track, moving_handle_key, moving_handle_right); undo_redo->add_undo_method(animation.ptr(), "bezier_track_set_key_in_handle", track, moving_handle_key, animation->bezier_track_get_key_in_handle(track, moving_handle_key)); @@ -839,7 +839,7 @@ void AnimationBezierTrackEdit::_gui_input(const Ref<InputEvent> &p_event) { if (moving_selection) { //combit it - undo_redo->create_action("Move Bezier Points"); + undo_redo->create_action(TTR("Move Bezier Points")); List<AnimMoveRestore> to_restore; // 1-remove the keys @@ -1053,7 +1053,7 @@ void AnimationBezierTrackEdit::_menu_selected(int p_index) { time += 0.001; } - undo_redo->create_action("Add Bezier Point"); + undo_redo->create_action(TTR("Add Bezier Point")); undo_redo->add_do_method(animation.ptr(), "track_insert_key", track, time, new_point); undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_position", track, time); undo_redo->commit_action(); diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp index 0ba45a596e..6b45ca2cae 100644 --- a/editor/animation_track_editor.cpp +++ b/editor/animation_track_editor.cpp @@ -45,18 +45,22 @@ class AnimationTrackKeyEdit : public Object { public: bool setting; - bool hidden; bool _hide_script_from_inspector() { return true; } + bool _dont_undo_redo() { + return true; + } + static void _bind_methods() { ClassDB::bind_method("_update_obj", &AnimationTrackKeyEdit::_update_obj); ClassDB::bind_method("_key_ofs_changed", &AnimationTrackKeyEdit::_key_ofs_changed); ClassDB::bind_method("_hide_script_from_inspector", &AnimationTrackKeyEdit::_hide_script_from_inspector); ClassDB::bind_method("get_root_path", &AnimationTrackKeyEdit::get_root_path); + ClassDB::bind_method("_dont_undo_redo", &AnimationTrackKeyEdit::_dont_undo_redo); } //PopupDialog *ke_dialog; @@ -82,16 +86,13 @@ public: void _update_obj(const Ref<Animation> &p_anim) { if (setting) return; - if (hidden) - return; if (!(animation == p_anim)) return; + notify_change(); } void _key_ofs_changed(const Ref<Animation> &p_anim, float from, float to) { - if (hidden) - return; if (!(animation == p_anim)) return; if (from != key_ofs) @@ -131,7 +132,7 @@ public: if (existing != -1) { Variant v = animation->track_get_key_value(track, existing); - float trans = animation->track_get_key_transition(track, existing); + trans = animation->track_get_key_transition(track, existing); undo_redo->add_undo_method(animation.ptr(), "track_insert_key", track, new_time, v, trans); } @@ -168,6 +169,7 @@ public: undo_redo->add_do_method(this, "_update_obj", animation); undo_redo->add_undo_method(this, "_update_obj", animation); undo_redo->commit_action(); + setting = false; return true; @@ -191,6 +193,7 @@ public: undo_redo->add_do_method(this, "_update_obj", animation); undo_redo->add_undo_method(this, "_update_obj", animation); undo_redo->commit_action(); + setting = false; return true; } @@ -267,6 +270,7 @@ public: undo_redo->add_do_method(this, "_update_obj", animation); undo_redo->add_undo_method(this, "_update_obj", animation); undo_redo->commit_action(); + setting = false; if (change_notify_deserved) notify_change(); @@ -286,6 +290,7 @@ public: undo_redo->add_do_method(this, "_update_obj", animation); undo_redo->add_undo_method(this, "_update_obj", animation); undo_redo->commit_action(); + setting = false; return true; } @@ -301,6 +306,7 @@ public: undo_redo->add_do_method(this, "_update_obj", animation); undo_redo->add_undo_method(this, "_update_obj", animation); undo_redo->commit_action(); + setting = false; return true; } @@ -316,6 +322,7 @@ public: undo_redo->add_do_method(this, "_update_obj", animation); undo_redo->add_undo_method(this, "_update_obj", animation); undo_redo->commit_action(); + setting = false; return true; } @@ -335,6 +342,7 @@ public: undo_redo->add_do_method(this, "_update_obj", animation); undo_redo->add_undo_method(this, "_update_obj", animation); undo_redo->commit_action(); + setting = false; return true; } @@ -350,6 +358,7 @@ public: undo_redo->add_do_method(this, "_update_obj", animation); undo_redo->add_undo_method(this, "_update_obj", animation); undo_redo->commit_action(); + setting = false; return true; } @@ -365,6 +374,7 @@ public: undo_redo->add_do_method(this, "_update_obj", animation); undo_redo->add_undo_method(this, "_update_obj", animation); undo_redo->commit_action(); + setting = false; return true; } @@ -374,12 +384,12 @@ public: if (name == "animation") { - StringName name = p_value; + StringName anim_name = p_value; setting = true; undo_redo->create_action(TTR("Anim Change Keyframe Value"), UndoRedo::MERGE_ENDS); StringName prev = animation->animation_track_get_key_animation(track, key); - undo_redo->add_do_method(animation.ptr(), "animation_track_set_key_animation", track, key, name); + undo_redo->add_do_method(animation.ptr(), "animation_track_set_key_animation", track, key, anim_name); undo_redo->add_undo_method(animation.ptr(), "animation_track_set_key_animation", track, key, prev); undo_redo->add_do_method(this, "_update_obj", animation); undo_redo->add_undo_method(this, "_update_obj", animation); @@ -649,7 +659,6 @@ public: } AnimationTrackKeyEdit() { - hidden = true; key_ofs = 0; track = -1; setting = false; @@ -684,7 +693,7 @@ void AnimationTimelineEdit::_anim_length_changed(double p_new_len) { editing = true; *block_animation_update_ptr = true; - undo_redo->create_action("Change animation length"); + undo_redo->create_action(TTR("Change Animation Length")); undo_redo->add_do_method(animation.ptr(), "set_length", p_new_len); undo_redo->add_undo_method(animation.ptr(), "set_length", animation->get_length()); undo_redo->commit_action(); @@ -698,7 +707,7 @@ void AnimationTimelineEdit::_anim_length_changed(double p_new_len) { void AnimationTimelineEdit::_anim_loop_pressed() { *block_animation_update_ptr = true; - undo_redo->create_action("Change animation loop"); + undo_redo->create_action(TTR("Change Animation Loop")); undo_redo->add_do_method(animation.ptr(), "set_loop", loop->is_pressed()); undo_redo->add_undo_method(animation.ptr(), "set_loop", animation->has_loop()); undo_redo->commit_action(); @@ -1685,7 +1694,7 @@ void AnimationTrackEdit::_zoom_changed() { } void AnimationTrackEdit::_path_entered(const String &p_text) { - undo_redo->create_action("Change Track Path"); + undo_redo->create_action(TTR("Change Track Path")); undo_redo->add_do_method(animation.ptr(), "track_set_path", track, p_text); undo_redo->add_undo_method(animation.ptr(), "track_set_path", track, animation->track_get_path(track)); undo_redo->commit_action(); @@ -1876,7 +1885,7 @@ void AnimationTrackEdit::_gui_input(const Ref<InputEvent> &p_event) { if (check_rect.has_point(pos)) { *block_animation_update_ptr = true; - undo_redo->create_action("Toggle track enabled"); + undo_redo->create_action(TTR("Toggle Track Enabled")); undo_redo->add_do_method(animation.ptr(), "track_set_enabled", track, !animation->track_is_enabled(track)); undo_redo->add_undo_method(animation.ptr(), "track_set_enabled", track, animation->track_is_enabled(track)); undo_redo->commit_action(); @@ -2178,7 +2187,7 @@ void AnimationTrackEdit::_menu_selected(int p_index) { Animation::UpdateMode update_mode = Animation::UpdateMode(p_index); *block_animation_update_ptr = true; - undo_redo->create_action("Change animation update mode"); + undo_redo->create_action(TTR("Change Animation Update Mode")); undo_redo->add_do_method(animation.ptr(), "value_track_set_update_mode", track, update_mode); undo_redo->add_undo_method(animation.ptr(), "value_track_set_update_mode", track, animation->value_track_get_update_mode(track)); undo_redo->commit_action(); @@ -2192,7 +2201,7 @@ void AnimationTrackEdit::_menu_selected(int p_index) { Animation::InterpolationType interp_mode = Animation::InterpolationType(p_index - MENU_INTERPOLATION_NEAREST); *block_animation_update_ptr = true; - undo_redo->create_action("Change animation interpolation mode"); + undo_redo->create_action(TTR("Change Animation Interpolation Mode")); undo_redo->add_do_method(animation.ptr(), "track_set_interpolation_type", track, interp_mode); undo_redo->add_undo_method(animation.ptr(), "track_set_interpolation_type", track, animation->track_get_interpolation_type(track)); undo_redo->commit_action(); @@ -2204,7 +2213,7 @@ void AnimationTrackEdit::_menu_selected(int p_index) { bool loop_wrap = p_index == MENU_LOOP_WRAP; *block_animation_update_ptr = true; - undo_redo->create_action("Change animation loop mode"); + undo_redo->create_action(TTR("Change Animation Loop Mode")); undo_redo->add_do_method(animation.ptr(), "track_set_interpolation_loop_wrap", track, loop_wrap); undo_redo->add_undo_method(animation.ptr(), "track_set_interpolation_loop_wrap", track, animation->track_get_interpolation_loop_wrap(track)); undo_redo->commit_action(); @@ -2824,9 +2833,9 @@ void AnimationTrackEditor::insert_node_value_key(Node *p_node, const String &p_p if (animation->track_get_path(i) == np) { value = p_value; //all good } else { - String path = animation->track_get_path(i); - if (NodePath(path.get_basename()) == np) { - String subindex = path.get_extension(); + String tpath = animation->track_get_path(i); + if (NodePath(tpath.get_basename()) == np) { + String subindex = tpath.get_extension(); value = p_value.get(subindex); } else { continue; @@ -2919,9 +2928,9 @@ void AnimationTrackEditor::insert_value_key(const String &p_property, const Vari if (animation->track_get_path(i) == np) { value = p_value; //all good } else { - String path = animation->track_get_path(i); - if (NodePath(path.get_basename()) == np) { - String subindex = path.get_extension(); + String tpath = animation->track_get_path(i); + if (NodePath(tpath.get_basename()) == np) { + String subindex = tpath.get_extension(); value = p_value.get(subindex); } else { continue; @@ -3209,14 +3218,6 @@ int AnimationTrackEditor::_confirm_insert(InsertData p_id, int p_last_track, boo } } - /* - undo_redo->add_do_method(this, "update_tracks"); - undo_redo->add_undo_method(this, "update"); - undo_redo->add_do_method(track_editor, "update"); - undo_redo->add_undo_method(track_editor, "update"); - undo_redo->add_do_method(track_pos, "update"); - undo_redo->add_undo_method(track_pos, "update"); -*/ undo_redo->commit_action(); return p_last_track; @@ -3414,6 +3415,14 @@ void AnimationTrackEditor::_update_tracks() { void AnimationTrackEditor::_animation_changed() { + if (key_edit && key_edit->setting) { + //if editing a key, just update the edited track, makes refresh less costly + if (key_edit->track < track_edits.size()) { + track_edits[key_edit->track]->update(); + } + return; + } + timeline->update(); timeline->update_values(); if (block_animation_update) { @@ -3469,7 +3478,7 @@ void AnimationTrackEditor::_update_scroll(double) { void AnimationTrackEditor::_update_step(double p_new_step) { - undo_redo->create_action("Change animation step"); + undo_redo->create_action(TTR("Change Animation Step")); undo_redo->add_do_method(animation.ptr(), "set_step", p_new_step); undo_redo->add_undo_method(animation.ptr(), "set_step", animation->get_step()); step->set_block_signals(true); @@ -3492,7 +3501,7 @@ void AnimationTrackEditor::_dropped_track(int p_from_track, int p_to_track) { return; _clear_selection(); - undo_redo->create_action("Rearrange tracks"); + undo_redo->create_action(TTR("Rearrange Tracks")); undo_redo->add_do_method(animation.ptr(), "track_swap", p_from_track, p_to_track); undo_redo->add_undo_method(animation.ptr(), "track_swap", p_to_track, p_from_track); undo_redo->commit_action(); @@ -3519,7 +3528,7 @@ void AnimationTrackEditor::_new_track_node_selected(NodePath p_path) { case Animation::TYPE_TRANSFORM: case Animation::TYPE_METHOD: { - undo_redo->create_action("Add Track"); + undo_redo->create_action(TTR("Add Track")); undo_redo->add_do_method(animation.ptr(), "add_track", adding_track_type); undo_redo->add_do_method(animation.ptr(), "track_set_path", animation->get_track_count(), path_to); undo_redo->add_undo_method(animation.ptr(), "remove_track", animation->get_track_count()); @@ -3548,7 +3557,7 @@ void AnimationTrackEditor::_new_track_node_selected(NodePath p_path) { return; } - undo_redo->create_action("Add Track"); + undo_redo->create_action(TTR("Add Track")); undo_redo->add_do_method(animation.ptr(), "add_track", adding_track_type); undo_redo->add_do_method(animation.ptr(), "track_set_path", animation->get_track_count(), path_to); undo_redo->add_undo_method(animation.ptr(), "remove_track", animation->get_track_count()); @@ -3567,7 +3576,7 @@ void AnimationTrackEditor::_new_track_node_selected(NodePath p_path) { return; } - undo_redo->create_action("Add Track"); + undo_redo->create_action(TTR("Add Track")); undo_redo->add_do_method(animation.ptr(), "add_track", adding_track_type); undo_redo->add_do_method(animation.ptr(), "track_set_path", animation->get_track_count(), path_to); undo_redo->add_undo_method(animation.ptr(), "remove_track", animation->get_track_count()); @@ -3619,7 +3628,7 @@ void AnimationTrackEditor::_new_track_property_selected(String p_name) { } } - undo_redo->create_action("Add Track"); + undo_redo->create_action(TTR("Add Track")); undo_redo->add_do_method(animation.ptr(), "add_track", adding_track_type); undo_redo->add_do_method(animation.ptr(), "track_set_path", animation->get_track_count(), full_path); undo_redo->add_do_method(animation.ptr(), "value_track_set_update_mode", animation->get_track_count(), update_mode); @@ -3642,7 +3651,7 @@ void AnimationTrackEditor::_new_track_property_selected(String p_name) { } } - undo_redo->create_action("Add Bezier Track"); + undo_redo->create_action(TTR("Add Bezier Track")); int base_track = animation->get_track_count(); for (int i = 0; i < subindices.size(); i++) { undo_redo->add_do_method(animation.ptr(), "add_track", adding_track_type); @@ -3710,7 +3719,7 @@ void AnimationTrackEditor::_insert_key_from_track(float p_ofs, int p_track) { Vector3 scale = xf.basis.get_scale_local(); Quat rot = xf.basis; - undo_redo->create_action("Add Transform Track Key"); + undo_redo->create_action(TTR("Add Transform Track Key")); undo_redo->add_do_method(animation.ptr(), "transform_track_insert_key", p_track, p_ofs, loc, rot, scale); undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_position", p_track, p_ofs); undo_redo->commit_action(); @@ -3722,7 +3731,7 @@ void AnimationTrackEditor::_insert_key_from_track(float p_ofs, int p_track) { Variant value; _find_hint_for_track(p_track, bp, &value); - undo_redo->create_action("Add Track Key"); + undo_redo->create_action(TTR("Add Track Key")); undo_redo->add_do_method(animation.ptr(), "track_insert_key", p_track, p_ofs, value); undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_position", p_track, p_ofs); undo_redo->commit_action(); @@ -3754,7 +3763,7 @@ void AnimationTrackEditor::_insert_key_from_track(float p_ofs, int p_track) { arr[3] = 0.25; arr[4] = 0; - undo_redo->create_action("Add Track Key"); + undo_redo->create_action(TTR("Add Track Key")); undo_redo->add_do_method(animation.ptr(), "track_insert_key", p_track, p_ofs, arr); undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_position", p_track, p_ofs); undo_redo->commit_action(); @@ -3767,7 +3776,7 @@ void AnimationTrackEditor::_insert_key_from_track(float p_ofs, int p_track) { ak["start_offset"] = 0; ak["end_offset"] = 0; - undo_redo->create_action("Add Track Key"); + undo_redo->create_action(TTR("Add Track Key")); undo_redo->add_do_method(animation.ptr(), "track_insert_key", p_track, p_ofs, ak); undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_position", p_track, p_ofs); undo_redo->commit_action(); @@ -3776,7 +3785,7 @@ void AnimationTrackEditor::_insert_key_from_track(float p_ofs, int p_track) { StringName anim = "[stop]"; - undo_redo->create_action("Add Track Key"); + undo_redo->create_action(TTR("Add Track Key")); undo_redo->add_do_method(animation.ptr(), "track_insert_key", p_track, p_ofs, anim); undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_position", p_track, p_ofs); undo_redo->commit_action(); @@ -3816,7 +3825,7 @@ void AnimationTrackEditor::_add_method_key(const String &p_method) { } d["args"] = params; - undo_redo->create_action("Add Method Track Key"); + undo_redo->create_action(TTR("Add Method Track Key")); undo_redo->add_do_method(animation.ptr(), "track_insert_key", insert_key_from_track_call_track, insert_key_from_track_call_ofs, d); undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_position", insert_key_from_track_call_track, insert_key_from_track_call_ofs); undo_redo->commit_action(); @@ -4066,7 +4075,9 @@ void AnimationTrackEditor::_move_selection_commit() { undo_redo->add_undo_method(this, "_select_at_anim", animation, E->key().track, oldpos); } + block_animation_update = true; //animation will change and this is triggered from a signal, so block updates undo_redo->commit_action(); + block_animation_update = false; moving_selection = false; for (int i = 0; i < track_edits.size(); i++) { @@ -4318,9 +4329,9 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) { text = node->get_name(); Vector<StringName> sn = path.get_subnames(); - for (int i = 0; i < sn.size(); i++) { + for (int j = 0; j < sn.size(); j++) { text += "."; - text += sn[i]; + text += sn[j]; } path = NodePath(node->get_path().get_names(), path.get_subnames(), true); //store full path instead for copying @@ -4397,7 +4408,7 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) { } int base_track = animation->get_track_count(); - undo_redo->create_action("Paste Tracks"); + undo_redo->create_action(TTR("Paste Tracks")); for (int i = 0; i < track_clipboard.size(); i++) { undo_redo->add_do_method(animation.ptr(), "add_track", track_clipboard[i].track_type); Node *exists = NULL; diff --git a/editor/animation_track_editor_plugins.cpp b/editor/animation_track_editor_plugins.cpp index 8c2c2b7f38..399d561e28 100644 --- a/editor/animation_track_editor_plugins.cpp +++ b/editor/animation_track_editor_plugins.cpp @@ -29,6 +29,7 @@ /*************************************************************************/ #include "animation_track_editor_plugins.h" + #include "editor/audio_stream_preview.h" #include "editor_resource_preview.h" #include "editor_scale.h" @@ -37,6 +38,7 @@ #include "scene/3d/sprite_3d.h" #include "scene/animation/animation_player.h" #include "servers/audio/audio_stream.h" + /// BOOL /// int AnimationTrackEditBool::get_key_height() const { @@ -247,9 +249,6 @@ void AnimationTrackEditAudio::draw_key(int p_index, float p_pixels_sec, int p_x, return; } - Ref<Font> font = get_font("font", "Label"); - float fh = int(font->get_height() * 1.5); - bool play = get_animation()->track_get_key_value(get_track(), p_index); if (play) { float len = stream->get_length(); @@ -285,8 +284,9 @@ void AnimationTrackEditAudio::draw_key(int p_index, float p_pixels_sec, int p_x, if (to_x <= from_x) return; - int h = get_size().height; - Rect2 rect = Rect2(from_x, (h - fh) / 2, to_x - from_x, fh); + Ref<Font> font = get_font("font", "Label"); + float fh = int(font->get_height() * 1.5); + Rect2 rect = Rect2(from_x, (get_size().height - fh) / 2, to_x - from_x, fh); draw_rect(rect, Color(0.25, 0.25, 0.25)); Vector<Vector2> lines; @@ -439,13 +439,13 @@ void AnimationTrackEditSpriteFrame::draw_key(int p_index, float p_pixels_sec, in return; } - int frame = get_animation()->track_get_key_value(get_track(), p_index); - Ref<Texture> texture; Rect2 region; if (Object::cast_to<Sprite>(object) || Object::cast_to<Sprite3D>(object)) { + int frame = get_animation()->track_get_key_value(get_track(), p_index); + texture = object->call("get_texture"); if (!texture.is_valid()) { AnimationTrackEdit::draw_key(p_index, p_pixels_sec, p_x, p_selected, p_clip_left, p_clip_right); @@ -1005,7 +1005,7 @@ void AnimationTrackEditTypeAudio::drop_data(const Point2 &p_point, const Variant } *get_block_animation_update_ptr() = true; - get_undo_redo()->create_action("Add Audio Track Clip"); + get_undo_redo()->create_action(TTR("Add Audio Track Clip")); get_undo_redo()->add_do_method(get_animation().ptr(), "audio_track_insert_key", get_track(), ofs, stream); get_undo_redo()->add_undo_method(get_animation().ptr(), "track_remove_key_at_position", get_track(), ofs); get_undo_redo()->commit_action(); @@ -1099,7 +1099,7 @@ void AnimationTrackEditTypeAudio::_gui_input(const Ref<InputEvent> &p_event) { if (len_resizing_start) { float prev_ofs = get_animation()->audio_track_get_key_start_offset(get_track(), len_resizing_index); *get_block_animation_update_ptr() = true; - get_undo_redo()->create_action("Change Audio Track Clip Start Offset"); + get_undo_redo()->create_action(TTR("Change Audio Track Clip Start Offset")); get_undo_redo()->add_do_method(get_animation().ptr(), "audio_track_set_key_start_offset", get_track(), len_resizing_index, prev_ofs + ofs_local); get_undo_redo()->add_undo_method(get_animation().ptr(), "audio_track_set_key_start_offset", get_track(), len_resizing_index, prev_ofs); get_undo_redo()->commit_action(); @@ -1108,7 +1108,7 @@ void AnimationTrackEditTypeAudio::_gui_input(const Ref<InputEvent> &p_event) { } else { float prev_ofs = get_animation()->audio_track_get_key_end_offset(get_track(), len_resizing_index); *get_block_animation_update_ptr() = true; - get_undo_redo()->create_action("Change Audio Track Clip End Offset"); + get_undo_redo()->create_action(TTR("Change Audio Track Clip End Offset")); get_undo_redo()->add_do_method(get_animation().ptr(), "audio_track_set_key_end_offset", get_track(), len_resizing_index, prev_ofs + ofs_local); get_undo_redo()->add_undo_method(get_animation().ptr(), "audio_track_set_key_end_offset", get_track(), len_resizing_index, prev_ofs); get_undo_redo()->commit_action(); diff --git a/editor/array_property_edit.cpp b/editor/array_property_edit.cpp index 7a3edfde50..72beeaaf45 100644 --- a/editor/array_property_edit.cpp +++ b/editor/array_property_edit.cpp @@ -288,12 +288,17 @@ Node *ArrayPropertyEdit::get_node() { return Object::cast_to<Node>(ObjectDB::get_instance(obj)); } +bool ArrayPropertyEdit::_dont_undo_redo() { + return true; +} + void ArrayPropertyEdit::_bind_methods() { ClassDB::bind_method(D_METHOD("_set_size"), &ArrayPropertyEdit::_set_size); ClassDB::bind_method(D_METHOD("_set_value"), &ArrayPropertyEdit::_set_value); ClassDB::bind_method(D_METHOD("_notif_change"), &ArrayPropertyEdit::_notif_change); ClassDB::bind_method(D_METHOD("_notif_changev"), &ArrayPropertyEdit::_notif_changev); + ClassDB::bind_method(D_METHOD("_dont_undo_redo"), &ArrayPropertyEdit::_dont_undo_redo); } ArrayPropertyEdit::ArrayPropertyEdit() { diff --git a/editor/array_property_edit.h b/editor/array_property_edit.h index b2a3564c8c..fd17ebe9f8 100644 --- a/editor/array_property_edit.h +++ b/editor/array_property_edit.h @@ -52,6 +52,8 @@ class ArrayPropertyEdit : public Reference { void _set_size(int p_size); void _set_value(int p_idx, const Variant &p_value); + bool _dont_undo_redo(); + protected: static void _bind_methods(); bool _set(const StringName &p_name, const Variant &p_value); diff --git a/editor/audio_stream_preview.cpp b/editor/audio_stream_preview.cpp index 1ddd4552d3..85db8b77f9 100644 --- a/editor/audio_stream_preview.cpp +++ b/editor/audio_stream_preview.cpp @@ -77,7 +77,7 @@ float AudioStreamPreview::get_min(float p_time, float p_time_next) const { time_to = time_from + 1; } - uint8_t vmin = 0; + uint8_t vmin = 255; for (int i = time_from; i < time_to; i++) { diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp index 4ab9a72694..e9580ae0d1 100644 --- a/editor/code_editor.cpp +++ b/editor/code_editor.cpp @@ -31,6 +31,7 @@ #include "code_editor.h" #include "core/os/keyboard.h" +#include "core/string_builder.h" #include "editor/editor_scale.h" #include "editor_node.h" #include "editor_settings.h" @@ -98,9 +99,6 @@ void FindReplaceBar::_notification(int p_what) { } else if (p_what == NOTIFICATION_VISIBILITY_CHANGED) { set_process_unhandled_input(is_visible_in_tree()); - if (is_visible_in_tree()) { - _update_size(); - } } else if (p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) { find_prev->set_icon(get_icon("MoveUp", "EditorIcons")); @@ -389,7 +387,6 @@ void FindReplaceBar::_show_search() { search_text->set_cursor_position(search_text->get_text().length()); search_current(); } - call_deferred("_update_size"); } void FindReplaceBar::popup_search() { @@ -482,11 +479,6 @@ void FindReplaceBar::set_text_edit(TextEdit *p_text_edit) { text_edit->connect("text_changed", this, "_editor_text_changed"); } -void FindReplaceBar::_update_size() { - - container->set_size(Size2(hbc->get_size().width, 1)); -} - void FindReplaceBar::_bind_methods() { ClassDB::bind_method("_unhandled_input", &FindReplaceBar::_unhandled_input); @@ -502,7 +494,6 @@ void FindReplaceBar::_bind_methods() { ClassDB::bind_method("_replace_all_pressed", &FindReplaceBar::_replace_all); ClassDB::bind_method("_search_options_changed", &FindReplaceBar::_search_options_changed); ClassDB::bind_method("_hide_pressed", &FindReplaceBar::_hide_bar); - ClassDB::bind_method("_update_size", &FindReplaceBar::_update_size); ADD_SIGNAL(MethodInfo("search")); ADD_SIGNAL(MethodInfo("error")); @@ -510,26 +501,16 @@ void FindReplaceBar::_bind_methods() { FindReplaceBar::FindReplaceBar() { - container = memnew(MarginContainer); - container->add_constant_override("margin_bottom", 5 * EDSCALE); - add_child(container); - container->set_clip_contents(true); - container->set_h_size_flags(SIZE_EXPAND_FILL); - replace_all_mode = false; preserve_cursor = false; - hbc = memnew(HBoxContainer); - container->add_child(hbc); - hbc->set_anchor_and_margin(MARGIN_RIGHT, 1, 0); - vbc_lineedit = memnew(VBoxContainer); - hbc->add_child(vbc_lineedit); + add_child(vbc_lineedit); vbc_lineedit->set_h_size_flags(SIZE_EXPAND_FILL); VBoxContainer *vbc_button = memnew(VBoxContainer); - hbc->add_child(vbc_button); + add_child(vbc_button); VBoxContainer *vbc_option = memnew(VBoxContainer); - hbc->add_child(vbc_option); + add_child(vbc_option); HBoxContainer *hbc_button_search = memnew(HBoxContainer); vbc_button->add_child(hbc_button_search); @@ -673,18 +654,14 @@ void CodeTextEditor::_reset_zoom() { if (font.is_valid()) { EditorSettings::get_singleton()->set("interface/editor/code_font_size", 14); font->set_size(14); - font_size_nb->set_text("14 (100%)"); } } void CodeTextEditor::_line_col_changed() { - line_nb->set_text(itos(text_editor->cursor_get_line() + 1)); - String line = text_editor->get_line(text_editor->cursor_get_line()); int positional_column = 0; - for (int i = 0; i < text_editor->cursor_get_column(); i++) { if (line[i] == '\t') { positional_column += text_editor->get_indent_size(); //tab size @@ -693,7 +670,14 @@ void CodeTextEditor::_line_col_changed() { } } - col_nb->set_text(itos(positional_column + 1)); + StringBuilder *sb = memnew(StringBuilder); + sb->append("("); + sb->append(itos(text_editor->cursor_get_line() + 1).lpad(3)); + sb->append(","); + sb->append(itos(positional_column + 1).lpad(3)); + sb->append(")"); + + line_and_col_txt->set_text(sb->as_string()); } void CodeTextEditor::_text_changed() { @@ -747,8 +731,6 @@ bool CodeTextEditor::_add_font_size(int p_delta) { if (font.is_valid()) { int new_size = CLAMP(font->get_size() + p_delta, 8 * EDSCALE, 96 * EDSCALE); - font_size_nb->set_text(itos(new_size) + " (" + itos(100 * new_size / (14 * EDSCALE)) + "%)"); - if (new_size != font->get_size()) { EditorSettings::get_singleton()->set("interface/editor/code_font_size", new_size / EDSCALE); font->set_size(new_size); @@ -1060,35 +1042,43 @@ void CodeTextEditor::delete_lines() { } void CodeTextEditor::clone_lines_down() { + const int cursor_column = text_editor->cursor_get_column(); int from_line = text_editor->cursor_get_line(); int to_line = text_editor->cursor_get_line(); - int column = text_editor->cursor_get_column(); - + int from_column = 0; + int to_column = 0; + int cursor_new_line = to_line + 1; + int cursor_new_column = text_editor->cursor_get_column(); + String new_text = "\n" + text_editor->get_line(from_line); + bool selection_active = false; + + text_editor->cursor_set_column(text_editor->get_line(from_line).length()); if (text_editor->is_selection_active()) { + from_column = text_editor->get_selection_from_column(); + to_column = text_editor->get_selection_to_column(); + from_line = text_editor->get_selection_from_line(); to_line = text_editor->get_selection_to_line(); - column = text_editor->cursor_get_column(); + cursor_new_line = to_line + text_editor->cursor_get_line() - from_line; + cursor_new_column = to_column == cursor_column ? 2 * to_column - from_column : to_column; + new_text = text_editor->get_selection_text(); + selection_active = true; + + text_editor->cursor_set_line(to_line); + text_editor->cursor_set_column(to_column); } - int next_line = to_line + 1; - bool caret_at_start = text_editor->cursor_get_line() == from_line; text_editor->begin_complex_operation(); + for (int i = from_line; i <= to_line; i++) { text_editor->unfold_line(i); - text_editor->set_line(next_line - 1, text_editor->get_line(next_line - 1) + "\n"); - text_editor->set_line(next_line, text_editor->get_line(i)); - next_line++; - } - - if (caret_at_start) { - text_editor->cursor_set_line(to_line + 1); - } else { - text_editor->cursor_set_line(next_line - 1); } - - text_editor->cursor_set_column(column); - if (text_editor->is_selection_active()) { - text_editor->select(to_line + 1, text_editor->get_selection_from_column(), next_line - 1, text_editor->get_selection_to_column()); + text_editor->deselect(); + text_editor->insert_text_at_cursor(new_text); + text_editor->cursor_set_line(cursor_new_line); + text_editor->cursor_set_column(cursor_new_column); + if (selection_active) { + text_editor->select(to_line, to_column, 2 * to_line - from_line, 2 * to_column - from_column); } text_editor->end_complex_operation(); @@ -1167,7 +1157,6 @@ void CodeTextEditor::_on_settings_change() { _update_font(); font_size = EditorSettings::get_singleton()->get("interface/editor/code_font_size"); - font_size_nb->set_text(itos(font_size) + " (" + itos(100 * font_size / (14 * EDSCALE)) + "%)"); // AUTO BRACE COMPLETION text_editor->set_auto_brace_completion( @@ -1188,17 +1177,56 @@ void CodeTextEditor::_text_changed_idle_timeout() { emit_signal("validate_script"); } -void CodeTextEditor::_notification(int p_what) { +void CodeTextEditor::_warning_label_gui_input(const Ref<InputEvent> &p_event) { + Ref<InputEventMouseButton> mb = p_event; + if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { + _warning_button_pressed(); + } +} - if (p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) { - _load_theme_settings(); - emit_signal("load_theme_settings"); +void CodeTextEditor::_warning_button_pressed() { + _set_show_warnings_panel(!is_warnings_panel_opened); +} + +void CodeTextEditor::_set_show_warnings_panel(bool p_show) { + is_warnings_panel_opened = p_show; + emit_signal("show_warnings_panel", p_show); +} + +void CodeTextEditor::_error_pressed(const Ref<InputEvent> &p_event) { + Ref<InputEventMouseButton> mb = p_event; + if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { + emit_signal("error_pressed"); } - if (p_what == NOTIFICATION_THEME_CHANGED) { - _update_font(); +} + +void CodeTextEditor::_notification(int p_what) { + + switch (p_what) { + case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { + _load_theme_settings(); + emit_signal("load_theme_settings"); + } break; + case NOTIFICATION_THEME_CHANGED: { + _update_font(); + } break; + case NOTIFICATION_ENTER_TREE: { + warning_button->set_icon(get_icon("NodeWarning", "EditorIcons")); + add_constant_override("separation", 4 * EDSCALE); + } break; + default: + break; } } +void CodeTextEditor::set_warning_nb(int p_warning_nb) { + warning_count_label->set_text(itos(p_warning_nb)); + warning_count_label->set_visible(p_warning_nb > 0); + warning_button->set_visible(p_warning_nb > 0); + if (!p_warning_nb) + _set_show_warnings_panel(false); +} + void CodeTextEditor::_bind_methods() { ClassDB::bind_method("_text_editor_gui_input", &CodeTextEditor::_text_editor_gui_input); @@ -1209,9 +1237,14 @@ void CodeTextEditor::_bind_methods() { ClassDB::bind_method("_code_complete_timer_timeout", &CodeTextEditor::_code_complete_timer_timeout); ClassDB::bind_method("_complete_request", &CodeTextEditor::_complete_request); ClassDB::bind_method("_font_resize_timeout", &CodeTextEditor::_font_resize_timeout); + ClassDB::bind_method("_error_pressed", &CodeTextEditor::_error_pressed); + ClassDB::bind_method("_warning_button_pressed", &CodeTextEditor::_warning_button_pressed); + ClassDB::bind_method("_warning_label_gui_input", &CodeTextEditor::_warning_label_gui_input); ADD_SIGNAL(MethodInfo("validate_script")); ADD_SIGNAL(MethodInfo("load_theme_settings")); + ADD_SIGNAL(MethodInfo("show_warnings_panel")); + ADD_SIGNAL(MethodInfo("error_pressed")); } void CodeTextEditor::set_code_complete_func(CodeTextEditorCodeCompleteFunc p_code_complete_func, void *p_ud) { @@ -1226,15 +1259,16 @@ CodeTextEditor::CodeTextEditor() { ED_SHORTCUT("script_editor/zoom_out", TTR("Zoom Out"), KEY_MASK_CMD | KEY_MINUS); ED_SHORTCUT("script_editor/reset_zoom", TTR("Reset Zoom"), KEY_MASK_CMD | KEY_0); + text_editor = memnew(TextEdit); + add_child(text_editor); + text_editor->set_v_size_flags(SIZE_EXPAND_FILL); + + // Added second so it opens at the bottom, so it won't shift the entire text editor when opening. find_replace_bar = memnew(FindReplaceBar); add_child(find_replace_bar); find_replace_bar->set_h_size_flags(SIZE_EXPAND_FILL); find_replace_bar->hide(); - text_editor = memnew(TextEdit); - add_child(text_editor); - text_editor->set_v_size_flags(SIZE_EXPAND_FILL); - find_replace_bar->set_text_edit(text_editor); text_editor->set_show_line_numbers(true); @@ -1244,6 +1278,7 @@ CodeTextEditor::CodeTextEditor() { status_bar = memnew(HBoxContainer); add_child(status_bar); status_bar->set_h_size_flags(SIZE_EXPAND_FILL); + status_bar->set_custom_minimum_size(Size2(0, 24 * EDSCALE)); // Adjust for the height of the warning icon. idle = memnew(Timer); add_child(idle); @@ -1258,95 +1293,51 @@ CodeTextEditor::CodeTextEditor() { error_line = 0; error_column = 0; + // Error + ScrollContainer *scroll = memnew(ScrollContainer); + scroll->set_h_size_flags(SIZE_EXPAND_FILL); + scroll->set_v_size_flags(SIZE_EXPAND_FILL); + scroll->set_enable_v_scroll(false); + status_bar->add_child(scroll); + error = memnew(Label); - status_bar->add_child(error); - error->set_autowrap(true); - error->set_valign(Label::VALIGN_CENTER); - error->set_h_size_flags(SIZE_EXPAND_FILL); //required for it to display, given now it's clipping contents, do not touch + scroll->add_child(error); + error->set_v_size_flags(SIZE_EXPAND | SIZE_SHRINK_CENTER); error->add_color_override("font_color", EditorNode::get_singleton()->get_gui_base()->get_color("error_color", "Editor")); error->add_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_font("status_source", "EditorFonts")); error->set_mouse_filter(MOUSE_FILTER_STOP); + error->connect("gui_input", this, "_error_pressed"); find_replace_bar->connect("error", error, "set_text"); - status_bar->add_child(memnew(Label)); //to keep the height if the other labels are not visible - - warning_label = memnew(Label); - status_bar->add_child(warning_label); - warning_label->set_align(Label::ALIGN_RIGHT); - warning_label->set_valign(Label::VALIGN_CENTER); - warning_label->set_v_size_flags(SIZE_FILL); - warning_label->set_default_cursor_shape(CURSOR_POINTING_HAND); - warning_label->set_mouse_filter(MOUSE_FILTER_STOP); - warning_label->set_text(TTR("Warnings:")); - warning_label->add_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_font("status_source", "EditorFonts")); + // Warnings + warning_button = memnew(ToolButton); + status_bar->add_child(warning_button); + warning_button->set_v_size_flags(SIZE_EXPAND | SIZE_SHRINK_CENTER); + warning_button->set_default_cursor_shape(CURSOR_POINTING_HAND); + warning_button->connect("pressed", this, "_warning_button_pressed"); + warning_button->set_tooltip(TTR("Warnings")); warning_count_label = memnew(Label); status_bar->add_child(warning_count_label); - warning_count_label->set_valign(Label::VALIGN_CENTER); - warning_count_label->set_v_size_flags(SIZE_FILL); - warning_count_label->set_autowrap(true); // workaround to prevent resizing the label on each change, do not touch - warning_count_label->set_clip_text(true); // workaround to prevent resizing the label on each change, do not touch - warning_count_label->set_custom_minimum_size(Size2(40, 1) * EDSCALE); + warning_count_label->set_v_size_flags(SIZE_EXPAND | SIZE_SHRINK_CENTER); warning_count_label->set_align(Label::ALIGN_RIGHT); warning_count_label->set_default_cursor_shape(CURSOR_POINTING_HAND); warning_count_label->set_mouse_filter(MOUSE_FILTER_STOP); + warning_count_label->set_tooltip(TTR("Warnings")); + warning_count_label->add_color_override("font_color", EditorNode::get_singleton()->get_gui_base()->get_color("warning_color", "Editor")); warning_count_label->add_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_font("status_source", "EditorFonts")); - warning_count_label->set_text("0"); - - Label *font_size_txt = memnew(Label); - status_bar->add_child(font_size_txt); - font_size_txt->set_align(Label::ALIGN_RIGHT); - font_size_txt->set_valign(Label::VALIGN_CENTER); - font_size_txt->set_v_size_flags(SIZE_FILL); - font_size_txt->set_text(TTR("Font Size:")); - font_size_txt->add_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_font("status_source", "EditorFonts")); - - font_size_nb = memnew(Label); - status_bar->add_child(font_size_nb); - font_size_nb->set_valign(Label::VALIGN_CENTER); - font_size_nb->set_v_size_flags(SIZE_FILL); - font_size_nb->set_autowrap(true); // workaround to prevent resizing the label on each change, do not touch - font_size_nb->set_clip_text(true); // workaround to prevent resizing the label on each change, do not touch - font_size_nb->set_custom_minimum_size(Size2(100, 1) * EDSCALE); - font_size_nb->set_align(Label::ALIGN_RIGHT); - font_size_nb->add_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_font("status_source", "EditorFonts")); - - Label *line_txt = memnew(Label); - status_bar->add_child(line_txt); - line_txt->set_align(Label::ALIGN_RIGHT); - line_txt->set_valign(Label::VALIGN_CENTER); - line_txt->set_v_size_flags(SIZE_FILL); - line_txt->set_text(TTR("Line:")); - line_txt->add_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_font("status_source", "EditorFonts")); - - line_nb = memnew(Label); - status_bar->add_child(line_nb); - line_nb->set_valign(Label::VALIGN_CENTER); - line_nb->set_v_size_flags(SIZE_FILL); - line_nb->set_autowrap(true); // workaround to prevent resizing the label on each change, do not touch - line_nb->set_clip_text(true); // workaround to prevent resizing the label on each change, do not touch - line_nb->set_custom_minimum_size(Size2(40, 1) * EDSCALE); - line_nb->set_align(Label::ALIGN_RIGHT); - line_nb->add_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_font("status_source", "EditorFonts")); - - Label *col_txt = memnew(Label); - status_bar->add_child(col_txt); - col_txt->set_align(Label::ALIGN_RIGHT); - col_txt->set_valign(Label::VALIGN_CENTER); - col_txt->set_v_size_flags(SIZE_FILL); - col_txt->set_text(TTR("Col:")); - col_txt->add_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_font("status_source", "EditorFonts")); - - col_nb = memnew(Label); - status_bar->add_child(col_nb); - col_nb->set_valign(Label::VALIGN_CENTER); - col_nb->set_v_size_flags(SIZE_FILL); - col_nb->set_autowrap(true); // workaround to prevent resizing the label on each change, do not touch - col_nb->set_clip_text(true); // workaround to prevent resizing the label on each change, do not touch - col_nb->set_custom_minimum_size(Size2(40, 1) * EDSCALE); - col_nb->set_align(Label::ALIGN_RIGHT); - col_nb->set("custom_constants/margin_right", 0); - col_nb->add_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_font("status_source", "EditorFonts")); + warning_count_label->connect("gui_input", this, "_warning_label_gui_input"); + + is_warnings_panel_opened = false; + set_warning_nb(0); + + // Line and column + line_and_col_txt = memnew(Label); + status_bar->add_child(line_and_col_txt); + line_and_col_txt->set_v_size_flags(SIZE_EXPAND | SIZE_SHRINK_CENTER); + line_and_col_txt->add_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_font("status_source", "EditorFonts")); + line_and_col_txt->set_tooltip(TTR("Line and column numbers.")); + line_and_col_txt->set_mouse_filter(MOUSE_FILTER_STOP); text_editor->connect("gui_input", this, "_text_editor_gui_input"); text_editor->connect("cursor_changed", this, "_line_col_changed"); @@ -1365,7 +1356,6 @@ CodeTextEditor::CodeTextEditor() { font_resize_val = 0; font_size = EditorSettings::get_singleton()->get("interface/editor/code_font_size"); - font_size_nb->set_text(itos(font_size) + " (" + itos(100 * font_size / (14 * EDSCALE)) + "%)"); font_resize_timer = memnew(Timer); add_child(font_resize_timer); font_resize_timer->set_one_shot(true); diff --git a/editor/code_editor.h b/editor/code_editor.h index 96fc5b79e5..67e8fc9d3c 100644 --- a/editor/code_editor.h +++ b/editor/code_editor.h @@ -63,7 +63,6 @@ class FindReplaceBar : public HBoxContainer { GDCLASS(FindReplaceBar, HBoxContainer); - MarginContainer *container; LineEdit *search_text; ToolButton *find_prev; ToolButton *find_next; @@ -76,7 +75,6 @@ class FindReplaceBar : public HBoxContainer { Button *replace_all; CheckBox *selection_only; - HBoxContainer *hbc; VBoxContainer *vbc_lineedit; HBoxContainer *hbc_button_replace; HBoxContainer *hbc_option_replace; @@ -142,12 +140,12 @@ class CodeTextEditor : public VBoxContainer { TextEdit *text_editor; FindReplaceBar *find_replace_bar; HBoxContainer *status_bar; - Label *warning_label; + + ToolButton *warning_button; Label *warning_count_label; - Label *line_nb; - Label *col_nb; - Label *font_size_nb; + Label *line_and_col_txt; + Label *info; Timer *idle; Timer *code_complete_timer; @@ -176,6 +174,11 @@ class CodeTextEditor : public VBoxContainer { CodeTextEditorCodeCompleteFunc code_complete_func; void *code_complete_ud; + void _warning_label_gui_input(const Ref<InputEvent> &p_event); + void _warning_button_pressed(); + void _set_show_warnings_panel(bool p_show); + void _error_pressed(const Ref<InputEvent> &p_event); + protected: virtual void _load_theme_settings() {} virtual void _validate_script() {} @@ -188,6 +191,8 @@ protected: void _notification(int); static void _bind_methods(); + bool is_warnings_panel_opened; + public: void trim_trailing_whitespace(); @@ -212,15 +217,14 @@ public: Variant get_edit_state(); void set_edit_state(const Variant &p_state); + void set_warning_nb(int p_warning_nb); + void update_editor_settings(); void set_error(const String &p_error); void set_error_pos(int p_line, int p_column); void update_line_and_column() { _line_col_changed(); } TextEdit *get_text_edit() { return text_editor; } FindReplaceBar *get_find_replace_bar() { return find_replace_bar; } - Label *get_error_label() const { return error; } - Label *get_warning_label() const { return warning_label; } - Label *get_warning_count_label() const { return warning_count_label; } virtual void apply_code() {} void goto_error(); diff --git a/editor/collada/collada.cpp b/editor/collada/collada.cpp index d004e30fb8..94e6d4ded0 100644 --- a/editor/collada/collada.cpp +++ b/editor/collada/collada.cpp @@ -2071,17 +2071,17 @@ void Collada::_parse_library(XMLParser &parser) { } else if (name == "geometry") { String id = parser.get_attribute_value("id"); - String name = parser.get_attribute_value_safe("name"); + String name2 = parser.get_attribute_value_safe("name"); while (parser.read() == OK) { if (parser.get_node_type() == XMLParser::NODE_ELEMENT) { if (parser.get_node_name() == "mesh") { - state.mesh_name_map[id] = (name != "") ? name : id; - _parse_mesh_geometry(parser, id, name); + state.mesh_name_map[id] = (name2 != "") ? name2 : id; + _parse_mesh_geometry(parser, id, name2); } else if (parser.get_node_name() == "spline") { - state.mesh_name_map[id] = (name != "") ? name : id; - _parse_curve_geometry(parser, id, name); + state.mesh_name_map[id] = (name2 != "") ? name2 : id; + _parse_curve_geometry(parser, id, name2); } else if (!parser.is_empty()) parser.skip_section(); } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "geometry") @@ -2356,9 +2356,8 @@ bool Collada::_optimize_skeletons(VisualScene *p_vscene, Node *p_node) { bool Collada::_move_geometry_to_skeletons(VisualScene *p_vscene, Node *p_node, List<Node *> *p_mgeom) { - // bind shape matrix escala los huesos y los hace gigantes, asi la matriz despues achica - // al modelo? - // solucion: aplicarle la bind shape matrix a los VERTICES, y si el objeto viene con escala, se la dejo me parece! + // Bind Shape Matrix scales the bones and makes them gigantic, so the matrix then shrinks the model? + // Solution: apply the Bind Shape Matrix to the VERTICES, and if the object comes scaled, it seems to be left alone! if (p_node->type == Node::TYPE_GEOMETRY) { diff --git a/editor/connections_dialog.cpp b/editor/connections_dialog.cpp index 7a5ebc5c00..f775a0a14b 100644 --- a/editor/connections_dialog.cpp +++ b/editor/connections_dialog.cpp @@ -766,7 +766,7 @@ void ConnectionsDock::update_tree() { while (base) { - List<MethodInfo> node_signals; + List<MethodInfo> node_signals2; Ref<Texture> icon; String name; @@ -774,7 +774,7 @@ void ConnectionsDock::update_tree() { Ref<Script> scr = selectedNode->get_script(); if (scr.is_valid()) { - scr->get_script_signal_list(&node_signals); + scr->get_script_signal_list(&node_signals2); if (scr->get_path().is_resource_file()) name = scr->get_path().get_file(); else @@ -787,7 +787,7 @@ void ConnectionsDock::update_tree() { } else { - ClassDB::get_signal_list(base, &node_signals, true); + ClassDB::get_signal_list(base, &node_signals2, true); if (has_icon(base, "EditorIcons")) { icon = get_icon(base, "EditorIcons"); } @@ -796,17 +796,17 @@ void ConnectionsDock::update_tree() { TreeItem *pitem = NULL; - if (node_signals.size()) { + if (node_signals2.size()) { pitem = tree->create_item(root); pitem->set_text(0, name); pitem->set_icon(0, icon); pitem->set_selectable(0, false); pitem->set_editable(0, false); pitem->set_custom_bg_color(0, get_color("prop_subsection", "Editor")); - node_signals.sort(); + node_signals2.sort(); } - for (List<MethodInfo>::Element *E = node_signals.front(); E; E = E->next()) { + for (List<MethodInfo>::Element *E = node_signals2.front(); E; E = E->next()) { MethodInfo &mi = E->get(); diff --git a/editor/create_dialog.cpp b/editor/create_dialog.cpp index 3c2bfdc04d..fbc23aa8e2 100644 --- a/editor/create_dialog.cpp +++ b/editor/create_dialog.cpp @@ -299,15 +299,15 @@ void CreateDialog::_update_search() { } else { bool found = false; - String type = I->get(); - while (type != "" && (cpp_type ? ClassDB::is_parent_class(type, base_type) : ed.script_class_is_parent(type, base_type)) && type != base_type) { - if (search_box->get_text().is_subsequence_ofi(type)) { + String type2 = I->get(); + while (type2 != "" && (cpp_type ? ClassDB::is_parent_class(type2, base_type) : ed.script_class_is_parent(type2, base_type)) && type2 != base_type) { + if (search_box->get_text().is_subsequence_ofi(type2)) { found = true; break; } - type = cpp_type ? ClassDB::get_parent_class(type) : ed.script_class_get_base(type); + type2 = cpp_type ? ClassDB::get_parent_class(type2) : ed.script_class_get_base(type2); } if (found) diff --git a/editor/dependency_editor.cpp b/editor/dependency_editor.cpp index f9f1e455f5..f559eb6cb2 100644 --- a/editor/dependency_editor.cpp +++ b/editor/dependency_editor.cpp @@ -475,7 +475,6 @@ void DependencyRemoveDialog::show(const Vector<String> &p_folders, const Vector< Vector<RemovedDependency> removed_deps; _find_all_removed_dependencies(EditorFileSystem::get_singleton()->get_filesystem(), removed_deps); removed_deps.sort(); - if (removed_deps.empty()) { owners->hide(); text->set_text(TTR("Remove selected files from the project? (no undo)")); @@ -486,6 +485,7 @@ void DependencyRemoveDialog::show(const Vector<String> &p_folders, const Vector< text->set_text(TTR("The files being removed are required by other resources in order for them to work.\nRemove them anyway? (no undo)")); popup_centered_minsize(Size2(500, 350)); } + EditorFileSystem::get_singleton()->scan_changes(); } void DependencyRemoveDialog::ok_pressed() { @@ -496,11 +496,15 @@ void DependencyRemoveDialog::ok_pressed() { res->set_path(""); } - // If the file we are deleting is the main scene, clear its definition. + // If the file we are deleting is the main scene or default environment, clear its definition. if (files_to_delete[i] == ProjectSettings::get_singleton()->get("application/run/main_scene")) { ProjectSettings::get_singleton()->set("application/run/main_scene", ""); } + if (files_to_delete[i] == ProjectSettings::get_singleton()->get("rendering/environment/default_environment")) { + ProjectSettings::get_singleton()->set("rendering/environment/default_environment", ""); + } + String path = OS::get_singleton()->get_resource_dir() + files_to_delete[i].replace_first("res://", "/"); print_verbose("Moving to trash: " + path); Error err = OS::get_singleton()->move_to_trash(path); diff --git a/editor/dictionary_property_edit.cpp b/editor/dictionary_property_edit.cpp index 483f5ae2d0..9f4096ca02 100644 --- a/editor/dictionary_property_edit.cpp +++ b/editor/dictionary_property_edit.cpp @@ -102,12 +102,17 @@ Node *DictionaryPropertyEdit::get_node() { return cast_to<Node>(o); } +bool DictionaryPropertyEdit::_dont_undo_redo() { + return true; +} + void DictionaryPropertyEdit::_bind_methods() { ClassDB::bind_method(D_METHOD("_set_key"), &DictionaryPropertyEdit::_set_key); ClassDB::bind_method(D_METHOD("_set_value"), &DictionaryPropertyEdit::_set_value); ClassDB::bind_method(D_METHOD("_notif_change"), &DictionaryPropertyEdit::_notif_change); ClassDB::bind_method(D_METHOD("_notif_changev"), &DictionaryPropertyEdit::_notif_changev); + ClassDB::bind_method(D_METHOD("_dont_undo_redo"), &DictionaryPropertyEdit::_dont_undo_redo); } bool DictionaryPropertyEdit::_set(const StringName &p_name, const Variant &p_value) { diff --git a/editor/dictionary_property_edit.h b/editor/dictionary_property_edit.h index f6bd13785a..a2a81c261c 100644 --- a/editor/dictionary_property_edit.h +++ b/editor/dictionary_property_edit.h @@ -46,6 +46,8 @@ class DictionaryPropertyEdit : public Reference { Variant get_dictionary() const; + bool _dont_undo_redo(); + protected: static void _bind_methods(); bool _set(const StringName &p_name, const Variant &p_value); diff --git a/editor/doc/doc_data.cpp b/editor/doc/doc_data.cpp index 24a746d159..8f1d0d9677 100644 --- a/editor/doc/doc_data.cpp +++ b/editor/doc/doc_data.cpp @@ -497,9 +497,9 @@ void DocData::generate(bool p_basic_types) { method.name = mi.name; - for (int i = 0; i < mi.arguments.size(); i++) { + for (int j = 0; j < mi.arguments.size(); j++) { - PropertyInfo arginfo = mi.arguments[i]; + PropertyInfo arginfo = mi.arguments[j]; ArgumentDoc ad; ad.name = arginfo.name; @@ -509,7 +509,7 @@ void DocData::generate(bool p_basic_types) { else ad.type = Variant::get_type_name(arginfo.type); - int defarg = mi.default_arguments.size() - mi.arguments.size() + i; + int defarg = mi.default_arguments.size() - mi.arguments.size() + j; if (defarg >= 0) ad.default_value = mi.default_arguments[defarg]; @@ -620,12 +620,12 @@ void DocData::generate(bool p_basic_types) { return_doc_from_retinfo(md, mi.return_val); - for (int i = 0; i < mi.arguments.size(); i++) { + for (int j = 0; j < mi.arguments.size(); j++) { ArgumentDoc ad; - argument_doc_from_arginfo(ad, mi.arguments[i]); + argument_doc_from_arginfo(ad, mi.arguments[j]); - int darg_idx = i - (mi.arguments.size() - mi.default_arguments.size()); + int darg_idx = j - (mi.arguments.size() - mi.default_arguments.size()); if (darg_idx >= 0) { Variant default_arg = E->get().default_arguments[darg_idx]; @@ -734,9 +734,9 @@ Error DocData::load_classes(const String &p_dir) { while (path != String()) { if (!isdir && path.ends_with("xml")) { Ref<XMLParser> parser = memnew(XMLParser); - Error err = parser->open(p_dir.plus_file(path)); - if (err) - return err; + Error err2 = parser->open(p_dir.plus_file(path)); + if (err2) + return err2; _load(parser); } @@ -806,78 +806,78 @@ Error DocData::_load(Ref<XMLParser> parser) { if (parser->get_node_type() == XMLParser::NODE_ELEMENT) { - String name = parser->get_node_name(); + String name2 = parser->get_node_name(); - if (name == "brief_description") { + if (name2 == "brief_description") { parser->read(); if (parser->get_node_type() == XMLParser::NODE_TEXT) c.brief_description = parser->get_node_data(); - } else if (name == "description") { + } else if (name2 == "description") { parser->read(); if (parser->get_node_type() == XMLParser::NODE_TEXT) c.description = parser->get_node_data(); - } else if (name == "tutorials") { + } else if (name2 == "tutorials") { while (parser->read() == OK) { if (parser->get_node_type() == XMLParser::NODE_ELEMENT) { - String name = parser->get_node_name(); + String name3 = parser->get_node_name(); - if (name == "link") { + if (name3 == "link") { parser->read(); if (parser->get_node_type() == XMLParser::NODE_TEXT) c.tutorials.push_back(parser->get_node_data().strip_edges()); } else { - ERR_EXPLAIN("Invalid tag in doc file: " + name); + ERR_EXPLAIN("Invalid tag in doc file: " + name3); ERR_FAIL_V(ERR_FILE_CORRUPT); } } else if (parser->get_node_type() == XMLParser::NODE_ELEMENT_END && parser->get_node_name() == "tutorials") break; //end of <tutorials> } - } else if (name == "demos") { + } else if (name2 == "demos") { parser->read(); if (parser->get_node_type() == XMLParser::NODE_TEXT) c.demos = parser->get_node_data(); - } else if (name == "methods") { + } else if (name2 == "methods") { - Error err = _parse_methods(parser, c.methods); - ERR_FAIL_COND_V(err, err); + Error err2 = _parse_methods(parser, c.methods); + ERR_FAIL_COND_V(err2, err2); - } else if (name == "signals") { + } else if (name2 == "signals") { - Error err = _parse_methods(parser, c.signals); - ERR_FAIL_COND_V(err, err); - } else if (name == "members") { + Error err2 = _parse_methods(parser, c.signals); + ERR_FAIL_COND_V(err2, err2); + } else if (name2 == "members") { while (parser->read() == OK) { if (parser->get_node_type() == XMLParser::NODE_ELEMENT) { - String name = parser->get_node_name(); + String name3 = parser->get_node_name(); - if (name == "member") { + if (name3 == "member") { - PropertyDoc prop; + PropertyDoc prop2; ERR_FAIL_COND_V(!parser->has_attribute("name"), ERR_FILE_CORRUPT); - prop.name = parser->get_attribute_value("name"); + prop2.name = parser->get_attribute_value("name"); ERR_FAIL_COND_V(!parser->has_attribute("type"), ERR_FILE_CORRUPT); - prop.type = parser->get_attribute_value("type"); + prop2.type = parser->get_attribute_value("type"); if (parser->has_attribute("setter")) - prop.setter = parser->get_attribute_value("setter"); + prop2.setter = parser->get_attribute_value("setter"); if (parser->has_attribute("getter")) - prop.getter = parser->get_attribute_value("getter"); + prop2.getter = parser->get_attribute_value("getter"); if (parser->has_attribute("enum")) - prop.enumeration = parser->get_attribute_value("enum"); + prop2.enumeration = parser->get_attribute_value("enum"); parser->read(); if (parser->get_node_type() == XMLParser::NODE_TEXT) - prop.description = parser->get_node_data(); - c.properties.push_back(prop); + prop2.description = parser->get_node_data(); + c.properties.push_back(prop2); } else { - ERR_EXPLAIN("Invalid tag in doc file: " + name); + ERR_EXPLAIN("Invalid tag in doc file: " + name3); ERR_FAIL_V(ERR_FILE_CORRUPT); } @@ -885,28 +885,28 @@ Error DocData::_load(Ref<XMLParser> parser) { break; //end of <constants> } - } else if (name == "theme_items") { + } else if (name2 == "theme_items") { while (parser->read() == OK) { if (parser->get_node_type() == XMLParser::NODE_ELEMENT) { - String name = parser->get_node_name(); + String name3 = parser->get_node_name(); - if (name == "theme_item") { + if (name3 == "theme_item") { - PropertyDoc prop; + PropertyDoc prop2; ERR_FAIL_COND_V(!parser->has_attribute("name"), ERR_FILE_CORRUPT); - prop.name = parser->get_attribute_value("name"); + prop2.name = parser->get_attribute_value("name"); ERR_FAIL_COND_V(!parser->has_attribute("type"), ERR_FILE_CORRUPT); - prop.type = parser->get_attribute_value("type"); + prop2.type = parser->get_attribute_value("type"); parser->read(); if (parser->get_node_type() == XMLParser::NODE_TEXT) - prop.description = parser->get_node_data(); - c.theme_properties.push_back(prop); + prop2.description = parser->get_node_data(); + c.theme_properties.push_back(prop2); } else { - ERR_EXPLAIN("Invalid tag in doc file: " + name); + ERR_EXPLAIN("Invalid tag in doc file: " + name3); ERR_FAIL_V(ERR_FILE_CORRUPT); } @@ -914,30 +914,30 @@ Error DocData::_load(Ref<XMLParser> parser) { break; //end of <constants> } - } else if (name == "constants") { + } else if (name2 == "constants") { while (parser->read() == OK) { if (parser->get_node_type() == XMLParser::NODE_ELEMENT) { - String name = parser->get_node_name(); + String name3 = parser->get_node_name(); - if (name == "constant") { + if (name3 == "constant") { - ConstantDoc constant; + ConstantDoc constant2; ERR_FAIL_COND_V(!parser->has_attribute("name"), ERR_FILE_CORRUPT); - constant.name = parser->get_attribute_value("name"); + constant2.name = parser->get_attribute_value("name"); ERR_FAIL_COND_V(!parser->has_attribute("value"), ERR_FILE_CORRUPT); - constant.value = parser->get_attribute_value("value"); + constant2.value = parser->get_attribute_value("value"); if (parser->has_attribute("enum")) { - constant.enumeration = parser->get_attribute_value("enum"); + constant2.enumeration = parser->get_attribute_value("enum"); } parser->read(); if (parser->get_node_type() == XMLParser::NODE_TEXT) - constant.description = parser->get_node_data(); - c.constants.push_back(constant); + constant2.description = parser->get_node_data(); + c.constants.push_back(constant2); } else { - ERR_EXPLAIN("Invalid tag in doc file: " + name); + ERR_EXPLAIN("Invalid tag in doc file: " + name3); ERR_FAIL_V(ERR_FILE_CORRUPT); } @@ -947,7 +947,7 @@ Error DocData::_load(Ref<XMLParser> parser) { } else { - ERR_EXPLAIN("Invalid tag in doc file: " + name); + ERR_EXPLAIN("Invalid tag in doc file: " + name2); ERR_FAIL_V(ERR_FILE_CORRUPT); } diff --git a/editor/editor_audio_buses.cpp b/editor/editor_audio_buses.cpp index 6593eb8f03..29e9cd01c5 100644 --- a/editor/editor_audio_buses.cpp +++ b/editor/editor_audio_buses.cpp @@ -365,7 +365,7 @@ void EditorAudioBus::_send_selected(int p_which) { updating_bus = true; UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); - ur->create_action("Select Audio Bus Send"); + ur->create_action(TTR("Select Audio Bus Send")); ur->add_do_method(AudioServer::get_singleton(), "set_bus_send", get_index(), send->get_item_text(p_which)); ur->add_undo_method(AudioServer::get_singleton(), "set_bus_send", get_index(), AudioServer::get_singleton()->get_bus_send(get_index())); ur->add_do_method(buses, "_update_bus", get_index()); @@ -385,9 +385,9 @@ void EditorAudioBus::_effect_selected() { if (effect->get_metadata(0) != Variant()) { int index = effect->get_metadata(0); - Ref<AudioEffect> effect = AudioServer::get_singleton()->get_bus_effect(get_index(), index); - if (effect.is_valid()) { - EditorNode::get_singleton()->push_item(effect.ptr()); + Ref<AudioEffect> effect2 = AudioServer::get_singleton()->get_bus_effect(get_index(), index); + if (effect2.is_valid()) { + EditorNode::get_singleton()->push_item(effect2.ptr()); } } @@ -1165,7 +1165,7 @@ EditorAudioBuses::EditorAudioBuses() { add = memnew(Button); top_hb->add_child(add); add->set_text(TTR("Add Bus")); - add->set_tooltip(TTR("Create a new Bus Layout.")); + add->set_tooltip(TTR("Add a new Audio Bus to this layout.")); add->connect("pressed", this, "_add_bus"); diff --git a/editor/editor_autoload_settings.cpp b/editor/editor_autoload_settings.cpp index 9534410590..2f2b0d2cba 100644 --- a/editor/editor_autoload_settings.cpp +++ b/editor/editor_autoload_settings.cpp @@ -598,8 +598,8 @@ void EditorAutoloadSettings::drop_data_fw(const Point2 &p_point, const Variant & int i = 0; - for (List<AutoLoadInfo>::Element *E = autoload_cache.front(); E; E = E->next()) { - orders.write[i++] = E->get().order; + for (List<AutoLoadInfo>::Element *F = autoload_cache.front(); F; F = F->next()) { + orders.write[i++] = F->get().order; } orders.sort(); @@ -610,9 +610,9 @@ void EditorAutoloadSettings::drop_data_fw(const Point2 &p_point, const Variant & i = 0; - for (List<AutoLoadInfo>::Element *E = autoload_cache.front(); E; E = E->next()) { - undo_redo->add_do_method(ProjectSettings::get_singleton(), "set_order", "autoload/" + E->get().name, orders[i++]); - undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set_order", "autoload/" + E->get().name, E->get().order); + for (List<AutoLoadInfo>::Element *F = autoload_cache.front(); F; F = F->next()) { + undo_redo->add_do_method(ProjectSettings::get_singleton(), "set_order", "autoload/" + F->get().name, orders[i++]); + undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set_order", "autoload/" + F->get().name, F->get().order); } orders.clear(); diff --git a/editor/editor_export.cpp b/editor/editor_export.cpp index 7c99318dca..39e6df4450 100644 --- a/editor/editor_export.cpp +++ b/editor/editor_export.cpp @@ -42,7 +42,7 @@ #include "editor/plugins/script_editor_plugin.h" #include "editor_node.h" #include "editor_settings.h" -#include "scene/resources/scene_format_text.h" +#include "scene/resources/resource_format_text.h" #include "thirdparty/misc/md5.h" static int _get_pad(int p_alignment, int p_n) { @@ -858,7 +858,7 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> & Vector<uint8_t> array = FileAccess::get_file_as_array(icon); p_func(p_udata, icon, array, idx, total); } - if (splash != String() && FileAccess::exists(splash)) { + if (splash != String() && FileAccess::exists(splash) && icon != splash) { Vector<uint8_t> array = FileAccess::get_file_as_array(splash); p_func(p_udata, splash, array, idx, total); } diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp index fe8d57d1a1..ea36410cc3 100644 --- a/editor/editor_file_system.cpp +++ b/editor/editor_file_system.cpp @@ -30,7 +30,7 @@ #include "editor_file_system.h" -#include "core/io/resource_import.h" +#include "core/io/resource_importer.h" #include "core/io/resource_loader.h" #include "core/io/resource_saver.h" #include "core/os/file_access.h" @@ -260,12 +260,12 @@ void EditorFileSystem::_scan_filesystem() { if (FileAccess::exists(update_cache)) { { - FileAccessRef f = FileAccess::open(update_cache, FileAccess::READ); - String l = f->get_line().strip_edges(); + FileAccessRef f2 = FileAccess::open(update_cache, FileAccess::READ); + String l = f2->get_line().strip_edges(); while (l != String()) { file_cache.erase(l); //erase cache for this, so it gets updated - l = f->get_line().strip_edges(); + l = f2->get_line().strip_edges(); } } @@ -686,17 +686,17 @@ void EditorFileSystem::_scan_new_dir(EditorFileSystemDirectory *p_dir, DirAccess _scan_new_dir(efd, da, p_progress.get_sub(idx, total)); - int idx = 0; + int idx2 = 0; for (int i = 0; i < p_dir->subdirs.size(); i++) { if (efd->name < p_dir->subdirs[i]->name) break; - idx++; + idx2++; } - if (idx == p_dir->subdirs.size()) { + if (idx2 == p_dir->subdirs.size()) { p_dir->subdirs.push_back(efd); } else { - p_dir->subdirs.insert(idx, efd); + p_dir->subdirs.insert(idx2, efd); } da->change_dir(".."); diff --git a/editor/editor_folding.cpp b/editor/editor_folding.cpp index 6ab41c641d..77c0f7491e 100644 --- a/editor/editor_folding.cpp +++ b/editor/editor_folding.cpp @@ -171,9 +171,9 @@ void EditorFolding::load_scene_folding(Node *p_scene, const String &p_path) { ERR_FAIL_COND(res_unfolds.size() & 1); for (int i = 0; i < unfolds.size(); i += 2) { - NodePath path = unfolds[i]; + NodePath path2 = unfolds[i]; PoolVector<String> un = unfolds[i + 1]; - Node *node = p_scene->get_node(path); + Node *node = p_scene->get_node_or_null(path2); if (!node) { continue; } @@ -181,17 +181,17 @@ void EditorFolding::load_scene_folding(Node *p_scene, const String &p_path) { } for (int i = 0; i < res_unfolds.size(); i += 2) { - String path = res_unfolds[i]; + String path2 = res_unfolds[i]; RES res; - if (ResourceCache::has(path)) { - res = RES(ResourceCache::get(path)); + if (ResourceCache::has(path2)) { + res = RES(ResourceCache::get(path2)); } if (res.is_null()) { continue; } - PoolVector<String> unfolds = res_unfolds[i + 1]; - _set_unfolds(res.ptr(), unfolds); + PoolVector<String> unfolds2 = res_unfolds[i + 1]; + _set_unfolds(res.ptr(), unfolds2); } } diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp index f8cee6883b..e0acc5cd70 100644 --- a/editor/editor_help.cpp +++ b/editor/editor_help.cpp @@ -1423,10 +1423,6 @@ EditorHelp::EditorHelp() { EDITOR_DEF("text_editor/help/sort_functions_alphabetically", true); - find_bar = memnew(FindBar); - add_child(find_bar); - find_bar->hide(); - class_desc = memnew(RichTextLabel); add_child(class_desc); class_desc->set_v_size_flags(SIZE_EXPAND_FILL); @@ -1434,13 +1430,16 @@ EditorHelp::EditorHelp() { class_desc->connect("meta_clicked", this, "_class_desc_select"); class_desc->connect("gui_input", this, "_class_desc_input"); + // Added second so it opens at the bottom so it won't offset the entire widget. + find_bar = memnew(FindBar); + add_child(find_bar); + find_bar->hide(); find_bar->set_rich_text_label(class_desc); class_desc->set_selection_enabled(true); scroll_locked = false; select_locked = false; - //set_process_unhandled_key_input(true); class_desc->hide(); } @@ -1509,7 +1508,6 @@ EditorHelpBit::EditorHelpBit() { rich_text = memnew(RichTextLabel); add_child(rich_text); - //rich_text->set_anchors_and_margins_preset(Control::PRESET_WIDE); rich_text->connect("meta_clicked", this, "_meta_clicked"); rich_text->add_color_override("selection_color", EditorSettings::get_singleton()->get("text_editor/theme/selection_color")); rich_text->set_override_selected_font_color(false); @@ -1518,38 +1516,25 @@ EditorHelpBit::EditorHelpBit() { FindBar::FindBar() { - container = memnew(Control); - add_child(container); - - container->set_clip_contents(true); - container->set_h_size_flags(SIZE_EXPAND_FILL); - - hbc = memnew(HBoxContainer); - container->add_child(hbc); - - vbc_search_text = memnew(VBoxContainer); - hbc->add_child(vbc_search_text); - vbc_search_text->set_h_size_flags(SIZE_EXPAND_FILL); - hbc->set_anchor_and_margin(MARGIN_RIGHT, 1, 0); - search_text = memnew(LineEdit); - vbc_search_text->add_child(search_text); + add_child(search_text); search_text->set_custom_minimum_size(Size2(100 * EDSCALE, 0)); + search_text->set_h_size_flags(SIZE_EXPAND_FILL); search_text->connect("text_changed", this, "_search_text_changed"); search_text->connect("text_entered", this, "_search_text_entered"); find_prev = memnew(ToolButton); - hbc->add_child(find_prev); + add_child(find_prev); find_prev->set_focus_mode(FOCUS_NONE); find_prev->connect("pressed", this, "_search_prev"); find_next = memnew(ToolButton); - hbc->add_child(find_next); + add_child(find_next); find_next->set_focus_mode(FOCUS_NONE); find_next->connect("pressed", this, "_search_next"); error_label = memnew(Label); - hbc->add_child(error_label); + add_child(error_label); error_label->add_color_override("font_color", EditorNode::get_singleton()->get_gui_base()->get_color("error_color", "Editor")); hide_button = memnew(TextureButton); @@ -1576,13 +1561,6 @@ void FindBar::popup_search() { _search(); } } - - call_deferred("_update_size"); -} - -void FindBar::_update_size() { - - container->set_custom_minimum_size(Size2(0, hbc->get_size().height)); } void FindBar::_notification(int p_what) { @@ -1618,7 +1596,6 @@ void FindBar::_bind_methods() { ClassDB::bind_method("_search_next", &FindBar::search_next); ClassDB::bind_method("_search_prev", &FindBar::search_prev); ClassDB::bind_method("_hide_pressed", &FindBar::_hide_bar); - ClassDB::bind_method("_update_size", &FindBar::_update_size); ADD_SIGNAL(MethodInfo("search")); } @@ -1677,7 +1654,7 @@ void FindBar::_unhandled_input(const Ref<InputEvent> &p_event) { Ref<InputEventKey> k = p_event; if (k.is_valid()) { - if (k->is_pressed() && (rich_text_label->has_focus() || hbc->is_a_parent_of(get_focus_owner()))) { + if (k->is_pressed() && (rich_text_label->has_focus() || is_a_parent_of(get_focus_owner()))) { bool accepted = true; diff --git a/editor/editor_help.h b/editor/editor_help.h index 133d98f81f..a50ab8a9f9 100644 --- a/editor/editor_help.h +++ b/editor/editor_help.h @@ -34,6 +34,7 @@ #include "editor/code_editor.h" #include "editor/doc/doc_data.h" #include "editor/editor_plugin.h" +#include "scene/gui/margin_container.h" #include "scene/gui/menu_button.h" #include "scene/gui/panel_container.h" #include "scene/gui/rich_text_label.h" @@ -52,10 +53,6 @@ class FindBar : public HBoxContainer { TextureButton *hide_button; String prev_search; - Control *container; - HBoxContainer *hbc; - VBoxContainer *vbc_search_text; - RichTextLabel *rich_text_label; void _show_search(); diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp index 1078fabc2e..e8ee5069a5 100644 --- a/editor/editor_inspector.cpp +++ b/editor/editor_inspector.cpp @@ -215,14 +215,14 @@ void EditorProperty::_notification(int p_what) { else checkbox = get_icon("unchecked", "CheckBox"); - Color color(1, 1, 1); + Color color2(1, 1, 1); if (check_hover) { - color.r *= 1.2; - color.g *= 1.2; - color.b *= 1.2; + color2.r *= 1.2; + color2.g *= 1.2; + color2.b *= 1.2; } check_rect = Rect2(ofs, ((size.height - checkbox->get_height()) / 2), checkbox->get_width(), checkbox->get_height()); - draw_texture(checkbox, check_rect.position, color); + draw_texture(checkbox, check_rect.position, color2); ofs += get_constant("hseparator", "Tree"); ofs += checkbox->get_width(); } else { @@ -236,14 +236,14 @@ void EditorProperty::_notification(int p_what) { text_limit -= reload_icon->get_width() + get_constant("hseparator", "Tree") * 2; revert_rect = Rect2(text_limit + get_constant("hseparator", "Tree"), (size.height - reload_icon->get_height()) / 2, reload_icon->get_width(), reload_icon->get_height()); - Color color(1, 1, 1); + Color color2(1, 1, 1); if (revert_hover) { - color.r *= 1.2; - color.g *= 1.2; - color.b *= 1.2; + color2.r *= 1.2; + color2.g *= 1.2; + color2.b *= 1.2; } - draw_texture(reload_icon, revert_rect.position, color); + draw_texture(reload_icon, revert_rect.position, color2); } else { revert_rect = Rect2(); } @@ -262,14 +262,14 @@ void EditorProperty::_notification(int p_what) { ofs = size.width - key->get_width() - get_constant("hseparator", "Tree"); - Color color(1, 1, 1); + Color color2(1, 1, 1); if (keying_hover) { - color.r *= 1.2; - color.g *= 1.2; - color.b *= 1.2; + color2.r *= 1.2; + color2.g *= 1.2; + color2.b *= 1.2; } keying_rect = Rect2(ofs, ((size.height - key->get_height()) / 2), key->get_width(), key->get_height()); - draw_texture(key, keying_rect.position, color); + draw_texture(key, keying_rect.position, color2); } else { keying_rect = Rect2(); } @@ -1482,19 +1482,19 @@ void EditorInspector::update_tree() { category->bg_color = get_color("prop_category", "Editor"); if (use_doc_hints) { - StringName type = p.name; - if (!class_descr_cache.has(type)) { + StringName type2 = p.name; + if (!class_descr_cache.has(type2)) { String descr; DocData *dd = EditorHelp::get_doc_data(); - Map<String, DocData::ClassDoc>::Element *E = dd->class_list.find(type); + Map<String, DocData::ClassDoc>::Element *E = dd->class_list.find(type2); if (E) { descr = E->get().brief_description; } - class_descr_cache[type] = descr.word_wrap(80); + class_descr_cache[type2] = descr.word_wrap(80); } - category->set_tooltip(p.name + "::" + (class_descr_cache[type] == "" ? "" : class_descr_cache[type])); + category->set_tooltip(p.name + "::" + (class_descr_cache[type2] == "" ? "" : class_descr_cache[type2])); } for (List<Ref<EditorInspectorPlugin> >::Element *E = valid_plugins.front(); E; E = E->next()) { @@ -1639,16 +1639,16 @@ void EditorInspector::update_tree() { if (!found) { DocData *dd = EditorHelp::get_doc_data(); - Map<String, DocData::ClassDoc>::Element *E = dd->class_list.find(classname); - while (E && descr == String()) { - for (int i = 0; i < E->get().properties.size(); i++) { - if (E->get().properties[i].name == propname.operator String()) { - descr = E->get().properties[i].description.strip_edges().word_wrap(80); + Map<String, DocData::ClassDoc>::Element *F = dd->class_list.find(classname); + while (F && descr == String()) { + for (int i = 0; i < F->get().properties.size(); i++) { + if (F->get().properties[i].name == propname.operator String()) { + descr = F->get().properties[i].description.strip_edges().word_wrap(80); break; } } - if (!E->get().inherits.empty()) { - E = dd->class_list.find(E->get().inherits); + if (!F->get().inherits.empty()) { + F = dd->class_list.find(F->get().inherits); } else { break; } @@ -1937,7 +1937,7 @@ void EditorInspector::_edit_set(const String &p_name, const Variant &p_value, bo } } - if (!undo_redo || Object::cast_to<ArrayPropertyEdit>(object) || Object::cast_to<DictionaryPropertyEdit>(object)) { //kind of hacky + if (!undo_redo || bool(object->call("_dont_undo_redo"))) { object->set(p_name, p_value); if (p_refresh_all) diff --git a/editor/editor_log.cpp b/editor/editor_log.cpp index 803d7e10f7..aaca47622d 100644 --- a/editor/editor_log.cpp +++ b/editor/editor_log.cpp @@ -65,7 +65,6 @@ void EditorLog::_notification(int p_what) { } else if (p_what == NOTIFICATION_THEME_CHANGED) { Ref<DynamicFont> df_output_code = get_font("output_source", "EditorFonts"); if (df_output_code.is_valid()) { - df_output_code->set_size(int(EDITOR_DEF("run/output/font_size", 13)) * EDSCALE); if (log != NULL) { log->add_font_override("normal_font", get_font("output_source", "EditorFonts")); } @@ -132,7 +131,6 @@ void EditorLog::_bind_methods() { EditorLog::EditorLog() { VBoxContainer *vb = this; - add_constant_override("separation", get_constant("separation", "VBoxContainer")); HBoxContainer *hb = memnew(HBoxContainer); vb->add_child(hb); @@ -163,6 +161,8 @@ EditorLog::EditorLog() { current = Thread::get_caller_id(); + add_constant_override("separation", get_constant("separation", "VBoxContainer")); + EditorNode::get_undo_redo()->set_commit_notify_callback(_undo_redo_cbk, this); } diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index c8e00b0586..8c9974404e 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -326,7 +326,6 @@ void EditorNode::_notification(int p_what) { gui_base->set_theme(theme); gui_base->add_style_override("panel", gui_base->get_stylebox("Background", "EditorStyles")); - play_button_panel->add_style_override("panel", gui_base->get_stylebox("PlayButtonPanel", "EditorStyles")); scene_root_parent->add_style_override("panel", gui_base->get_stylebox("Content", "EditorStyles")); bottom_panel->add_style_override("panel", gui_base->get_stylebox("panel", "TabContainer")); scene_tabs->add_style_override("tab_fg", gui_base->get_stylebox("SceneTabFG", "EditorStyles")); @@ -881,9 +880,9 @@ bool EditorNode::_find_and_save_edited_subresources(Object *obj, Map<RES, bool> Dictionary d = obj->get(E->get().name); List<Variant> keys; d.get_key_list(&keys); - for (List<Variant>::Element *E = keys.front(); E; E = E->next()) { + for (List<Variant>::Element *F = keys.front(); F; F = F->next()) { - Variant v = d[E->get()]; + Variant v = d[F->get()]; RES res = v; if (_find_and_save_resource(res, processed, flags)) ret_changed = true; @@ -1371,6 +1370,9 @@ bool EditorNode::item_has_editor(Object *p_object) { return editor_data.get_subeditors(p_object).size() > 0; } +void EditorNode::edit_item_resource(RES p_resource) { + edit_item(p_resource.ptr()); +} void EditorNode::edit_item(Object *p_object) { Vector<EditorPlugin *> sub_plugins; @@ -2580,6 +2582,20 @@ void EditorNode::set_addon_plugin_enabled(const String &p_addon, bool p_enabled, Ref<ConfigFile> cf; cf.instance(); String addon_path = "res://addons/" + p_addon + "/plugin.cfg"; + if (!DirAccess::exists(addon_path.get_base_dir())) { + ProjectSettings *ps = ProjectSettings::get_singleton(); + PoolStringArray enabled_plugins = ps->get("editor_plugins/enabled"); + for (int i = 0; i < enabled_plugins.size(); ++i) { + if (enabled_plugins.get(i) == p_addon) { + enabled_plugins.remove(i); + break; + } + } + ps->set("editor_plugins/enabled", enabled_plugins); + ps->save(); + WARN_PRINTS("Addon '" + p_addon + "' failed to load. No directory found. Removing from enabled plugins."); + return; + } Error err = cf->load(addon_path); if (err != OK) { show_warning(vformat(TTR("Unable to enable addon plugin at: '%s' parsing of config failed."), addon_path)); @@ -2972,6 +2988,7 @@ Error EditorNode::load_scene(const String &p_scene, bool p_ignore_broken_deps, b prev_scene->set_disabled(previous_scenes.size() == 0); opening_prev = false; + scene_tree_dock->set_selected(new_scene); ScriptEditor::get_singleton()->get_debugger()->update_live_edit_root(); @@ -4405,7 +4422,7 @@ void EditorNode::remove_tool_menu_item(const String &p_name) { void EditorNode::_dropped_files(const Vector<String> &p_files, int p_screen) { - String to_path = ProjectSettings::get_singleton()->globalize_path(get_filesystem_dock()->get_current_path()); + String to_path = ProjectSettings::get_singleton()->globalize_path(get_filesystem_dock()->get_selected_path()); DirAccessRef dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); Vector<String> just_copy = String("ttf,otf").split(","); @@ -4716,6 +4733,7 @@ void EditorNode::_bind_methods() { ClassDB::bind_method("_clear_undo_history", &EditorNode::_clear_undo_history); ClassDB::bind_method("_dropped_files", &EditorNode::_dropped_files); ClassDB::bind_method("_toggle_distraction_free_mode", &EditorNode::_toggle_distraction_free_mode); + ClassDB::bind_method("edit_item_resource", &EditorNode::edit_item_resource); ClassDB::bind_method(D_METHOD("get_gui_base"), &EditorNode::get_gui_base); ClassDB::bind_method(D_METHOD("_bottom_panel_switch"), &EditorNode::_bottom_panel_switch); @@ -4767,8 +4785,6 @@ EditorNode::EditorNode() { ResourceLoader::clear_translation_remaps(); //no remaps using during editor ResourceLoader::clear_path_remaps(); - ImageTexture::set_keep_images_cached(true); - InputDefault *id = Object::cast_to<InputDefault>(Input::get_singleton()); if (id) { @@ -4886,9 +4902,9 @@ EditorNode::EditorNode() { import_collada.instance(); import_scene->add_importer(import_collada); - Ref<EditorOBJImporter> import_obj; - import_obj.instance(); - import_scene->add_importer(import_obj); + Ref<EditorOBJImporter> import_obj2; + import_obj2.instance(); + import_scene->add_importer(import_obj2); Ref<EditorSceneImporterGLTF> import_gltf; import_gltf.instance(); @@ -4990,7 +5006,7 @@ EditorNode::EditorNode() { main_vbox = memnew(VBoxContainer); gui_base->add_child(main_vbox); main_vbox->set_anchors_and_margins_preset(Control::PRESET_WIDE, Control::PRESET_MODE_MINSIZE, 8); - main_vbox->set_margin(MARGIN_TOP, 5 * EDSCALE); + main_vbox->add_constant_override("separation", 8 * EDSCALE); menu_hb = memnew(HBoxContainer); main_vbox->add_child(menu_hb); @@ -5202,11 +5218,8 @@ EditorNode::EditorNode() { viewport->add_constant_override("separation", 0); scene_root_parent->add_child(viewport); - PanelContainer *top_region = memnew(PanelContainer); - top_region->add_style_override("panel", gui_base->get_stylebox("MenuPanel", "EditorStyles")); HBoxContainer *left_menu_hb = memnew(HBoxContainer); - top_region->add_child(left_menu_hb); - menu_hb->add_child(top_region); + menu_hb->add_child(left_menu_hb); file_menu = memnew(MenuButton); file_menu->set_flat(false); @@ -5336,11 +5349,10 @@ EditorNode::EditorNode() { p->add_item(TTR("Quit to Project List"), RUN_PROJECT_MANAGER, KEY_MASK_SHIFT + KEY_MASK_CMD + KEY_Q); #endif - PanelContainer *editor_region = memnew(PanelContainer); - main_editor_button_vb = memnew(HBoxContainer); - editor_region->add_child(main_editor_button_vb); menu_hb->add_spacer(); - menu_hb->add_child(editor_region); + + main_editor_button_vb = memnew(HBoxContainer); + menu_hb->add_child(main_editor_button_vb); debug_menu = memnew(MenuButton); debug_menu->set_flat(false); @@ -5429,11 +5441,8 @@ EditorNode::EditorNode() { p->add_separator(); p->add_icon_item(gui_base->get_icon("Godot", "EditorIcons"), TTR("About"), HELP_ABOUT); - play_button_panel = memnew(PanelContainer); - menu_hb->add_child(play_button_panel); - HBoxContainer *play_hb = memnew(HBoxContainer); - play_button_panel->add_child(play_hb); + menu_hb->add_child(play_hb); play_button = memnew(ToolButton); play_hb->add_child(play_button); @@ -5511,7 +5520,6 @@ EditorNode::EditorNode() { video_driver = memnew(OptionButton); video_driver->set_flat(true); video_driver->set_focus_mode(Control::FOCUS_NONE); - video_driver->set_v_size_flags(Control::SIZE_SHRINK_CENTER); video_driver->connect("item_selected", this, "_video_driver_selected"); video_driver->add_font_override("font", gui_base->get_font("bold", "EditorFonts")); right_menu_hb->add_child(video_driver); @@ -5547,7 +5555,7 @@ EditorNode::EditorNode() { layout_dialog->connect("name_confirmed", this, "_dialog_action"); update_menu = memnew(MenuButton); - update_menu->set_tooltip(TTR("Spins when the editor window repaints!")); + update_menu->set_tooltip(TTR("Spins when the editor window redraws.")); right_menu_hb->add_child(update_menu); update_menu->set_icon(gui_base->get_icon("Progress1", "EditorIcons")); update_menu->get_popup()->connect("id_pressed", this, "_menu_option"); diff --git a/editor/editor_node.h b/editor/editor_node.h index a45ea54186..46a65b56fa 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -200,7 +200,6 @@ private: Control *theme_base; Control *gui_base; VBoxContainer *main_vbox; - PanelContainer *play_button_panel; OptionButton *video_driver; ConfirmationDialog *video_restart_dialog; @@ -674,6 +673,7 @@ public: void push_item(Object *p_object, const String &p_property = "", bool p_inspector_only = false); void edit_item(Object *p_object); + void edit_item_resource(RES p_resource); bool item_has_editor(Object *p_object); void open_request(const String &p_path); diff --git a/editor/editor_plugin_settings.cpp b/editor/editor_plugin_settings.cpp index ecc3b33a15..09577e39e1 100644 --- a/editor/editor_plugin_settings.cpp +++ b/editor/editor_plugin_settings.cpp @@ -92,9 +92,9 @@ void EditorPluginSettings::update_plugins() { cf.instance(); String path = "res://addons/" + plugins[i] + "/plugin.cfg"; - Error err = cf->load(path); + Error err2 = cf->load(path); - if (err != OK) { + if (err2 != OK) { WARN_PRINTS("Can't load plugin config: " + path); } else if (!cf->has_section_key("plugin", "name")) { WARN_PRINTS("Plugin misses plugin/name: " + path); @@ -108,7 +108,7 @@ void EditorPluginSettings::update_plugins() { WARN_PRINTS("Plugin misses plugin/script: " + path); } else { - String d = plugins[i]; + String d2 = plugins[i]; String name = cf->get_value("plugin", "name"); String author = cf->get_value("plugin", "author"); String version = cf->get_value("plugin", "version"); @@ -118,7 +118,7 @@ void EditorPluginSettings::update_plugins() { TreeItem *item = plugin_list->create_item(root); item->set_text(0, name); item->set_tooltip(0, "Name: " + name + "\nPath: " + path + "\nMain Script: " + script + "\nDescription: " + description); - item->set_metadata(0, d); + item->set_metadata(0, d2); item->set_text(1, version); item->set_metadata(1, script); item->set_text(2, author); @@ -129,7 +129,7 @@ void EditorPluginSettings::update_plugins() { item->set_editable(3, true); item->add_button(4, get_icon("Edit", "EditorIcons"), BUTTON_PLUGIN_EDIT, false, TTR("Edit Plugin")); - if (EditorNode::get_singleton()->is_addon_plugin_enabled(d)) { + if (EditorNode::get_singleton()->is_addon_plugin_enabled(d2)) { item->set_custom_color(3, get_color("success_color", "Editor")); item->set_range(3, 1); } else { diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp index 56bab440c9..a07cffb078 100644 --- a/editor/editor_properties.cpp +++ b/editor/editor_properties.cpp @@ -115,8 +115,8 @@ void EditorPropertyMultilineText::_open_big_text() { add_child(big_text_dialog); } - big_text->set_text(text->get_text()); big_text_dialog->popup_centered_ratio(); + big_text->set_text(text->get_text()); } void EditorPropertyMultilineText::update_property() { @@ -483,16 +483,16 @@ EditorPropertyCheck::EditorPropertyCheck() { void EditorPropertyEnum::_option_selected(int p_which) { - int val = options->get_item_metadata(p_which); + int64_t val = options->get_item_metadata(p_which); emit_changed(get_edited_property(), val); } void EditorPropertyEnum::update_property() { - int which = get_edited_object()->get(get_edited_property()); + int64_t which = get_edited_object()->get(get_edited_property()); for (int i = 0; i < options->get_item_count(); i++) { - if (which == (int)options->get_item_metadata(i)) { + if (which == (int64_t)options->get_item_metadata(i)) { options->select(i); return; } @@ -501,11 +501,11 @@ void EditorPropertyEnum::update_property() { void EditorPropertyEnum::setup(const Vector<String> &p_options) { - int current_val = 0; + int64_t current_val = 0; for (int i = 0; i < p_options.size(); i++) { Vector<String> text_split = p_options[i].split(":"); if (text_split.size() != 1) - current_val = text_split[1].to_int(); + current_val = text_split[1].to_int64(); options->add_item(text_split[0]); options->set_item_metadata(i, current_val); current_val += 1; @@ -665,10 +665,10 @@ public: uint32_t idx = i * 10 + j; bool on = value & (1 << idx); - Rect2 rect = Rect2(o, Size2(bsize, bsize)); + Rect2 rect2 = Rect2(o, Size2(bsize, bsize)); color.a = on ? 0.6 : 0.2; - draw_rect(rect, color); - flag_rects.push_back(rect); + draw_rect(rect2, color); + flag_rects.push_back(rect2); } } } @@ -801,11 +801,11 @@ EditorPropertyLayers::EditorPropertyLayers() { void EditorPropertyInteger::_value_changed(double val) { if (setting) return; - emit_changed(get_edited_property(), int(val)); + emit_changed(get_edited_property(), (int64_t)val); } void EditorPropertyInteger::update_property() { - int val = get_edited_object()->get(get_edited_property()); + int64_t val = get_edited_object()->get(get_edited_property()); setting = true; spin->set_value(val); setting = false; @@ -2277,8 +2277,8 @@ void EditorPropertyResource::_update_menu_items() { List<StringName> inheritors; ClassDB::get_inheriters_from_class(base.strip_edges(), &inheritors); - for (int i = 0; i < custom_resources.size(); i++) { - inheritors.push_back(custom_resources[i].name); + for (int j = 0; j < custom_resources.size(); j++) { + inheritors.push_back(custom_resources[j].name); } List<StringName>::Element *E = inheritors.front(); @@ -2287,17 +2287,17 @@ void EditorPropertyResource::_update_menu_items() { E = E->next(); } - for (Set<String>::Element *E = valid_inheritors.front(); E; E = E->next()) { - String t = E->get(); + for (Set<String>::Element *F = valid_inheritors.front(); F; F = F->next()) { + String t = F->get(); bool is_custom_resource = false; Ref<Texture> icon; if (!custom_resources.empty()) { - for (int i = 0; i < custom_resources.size(); i++) { - if (custom_resources[i].name == t) { + for (int j = 0; j < custom_resources.size(); j++) { + if (custom_resources[j].name == t) { is_custom_resource = true; - if (custom_resources[i].icon.is_valid()) - icon = custom_resources[i].icon; + if (custom_resources[j].icon.is_valid()) + icon = custom_resources[j].icon; break; } } @@ -2439,7 +2439,7 @@ void EditorPropertyResource::_button_input(const Ref<InputEvent> &p_event) { void EditorPropertyResource::_open_editor_pressed() { RES res = get_edited_object()->get(get_edited_property()); if (res.is_valid()) { - EditorNode::get_singleton()->edit_item(res.ptr()); + EditorNode::get_singleton()->call_deferred("edit_item_resource", res); //may clear the editor so do it deferred } } diff --git a/editor/editor_resource_preview.cpp b/editor/editor_resource_preview.cpp index f77f31db80..1fa1fe9070 100644 --- a/editor/editor_resource_preview.cpp +++ b/editor/editor_resource_preview.cpp @@ -155,7 +155,7 @@ void EditorResourcePreview::_generate_preview(Ref<ImageTexture> &r_texture, Ref< r_texture = generated; if (r_texture.is_valid() && preview_generators[i]->should_generate_small_preview()) { - int small_thumbnail_size = EditorNode::get_singleton()->get_theme_base()->get_icon("Object", "EditorIcons")->get_width(); // Kind of a workaround to retreive the default icon size + int small_thumbnail_size = EditorNode::get_singleton()->get_theme_base()->get_icon("Object", "EditorIcons")->get_width(); // Kind of a workaround to retrieve the default icon size small_thumbnail_size *= EDSCALE; Ref<Image> small_image = r_texture->get_data(); diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index 9973c7354e..cbd8df315a 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -575,6 +575,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { _initial_set("run/auto_save/save_before_running", true); // Output + hints["run/output/font_size"] = PropertyInfo(Variant::INT, "run/output/font_size", PROPERTY_HINT_RANGE, "8,96,1", PROPERTY_USAGE_DEFAULT); _initial_set("run/output/always_clear_output_on_play", true); _initial_set("run/output/always_open_output_on_play", true); _initial_set("run/output/always_close_output_on_stop", false); diff --git a/editor/editor_spin_slider.cpp b/editor/editor_spin_slider.cpp index 927ef9ab52..dcb106899e 100644 --- a/editor/editor_spin_slider.cpp +++ b/editor/editor_spin_slider.cpp @@ -213,14 +213,14 @@ void EditorSpinSlider::_notification(int p_what) { draw_string(font, Vector2(sb->get_offset().x + string_width + sep, vofs), numstr, fc, number_width); if (get_step() == 1) { - Ref<Texture> updown = get_icon("updown", "SpinBox"); - int updown_vofs = (get_size().height - updown->get_height()) / 2; - updown_offset = get_size().width - sb->get_margin(MARGIN_RIGHT) - updown->get_width(); + Ref<Texture> updown2 = get_icon("updown", "SpinBox"); + int updown_vofs = (get_size().height - updown2->get_height()) / 2; + updown_offset = get_size().width - sb->get_margin(MARGIN_RIGHT) - updown2->get_width(); Color c(1, 1, 1); if (hover_updown) { c *= Color(1.2, 1.2, 1.2); } - draw_texture(updown, Vector2(updown_offset, updown_vofs), c); + draw_texture(updown2, Vector2(updown_offset, updown_vofs), c); if (grabber->is_visible()) { grabber->hide(); } diff --git a/editor/editor_sub_scene.cpp b/editor/editor_sub_scene.cpp index 6a0a151aa9..e4807a37c6 100644 --- a/editor/editor_sub_scene.cpp +++ b/editor/editor_sub_scene.cpp @@ -187,8 +187,8 @@ void EditorSubScene::move(Node *p_new_parent, Node *p_new_owner) { } p_new_parent->add_child(selnode); - for (List<Node *>::Element *E = to_reown.front(); E; E = E->next()) { - E->get()->set_owner(p_new_owner); + for (List<Node *>::Element *F = to_reown.front(); F; F = F->next()) { + F->get()->set_owner(p_new_owner); } } if (!is_root) { diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp index 31655fed87..3fe19c0b31 100644 --- a/editor/editor_themes.cpp +++ b/editor/editor_themes.cpp @@ -286,7 +286,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { } else if (preset == "Solarized (Dark)") { preset_accent_color = Color::html("#268bd2"); preset_base_color = Color::html("#073642"); - preset_contrast = 0.15; + preset_contrast = 0.23; } else if (preset == "Solarized (Light)") { preset_accent_color = Color::html("#268bd2"); preset_base_color = Color::html("#fdf6e3"); @@ -481,6 +481,10 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { style_tab_unselected->set_bg_color(dark_color_1); style_tab_unselected->set_border_color_all(dark_color_2); + Ref<StyleBoxFlat> style_tab_disabled = style_tab_selected->duplicate(); + style_tab_disabled->set_bg_color(color_disabled_bg); + style_tab_disabled->set_border_color_all(color_disabled); + // Editor background theme->set_stylebox("Background", "EditorStyles", make_flat_stylebox(background_color, default_margin_size, default_margin_size, default_margin_size, default_margin_size)); @@ -742,8 +746,10 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { // Tabs & TabContainer theme->set_stylebox("tab_fg", "TabContainer", style_tab_selected); theme->set_stylebox("tab_bg", "TabContainer", style_tab_unselected); + theme->set_stylebox("tab_disabled", "TabContainer", style_tab_disabled); theme->set_stylebox("tab_fg", "Tabs", style_tab_selected); theme->set_stylebox("tab_bg", "Tabs", style_tab_unselected); + theme->set_stylebox("tab_disabled", "Tabs", style_tab_disabled); theme->set_color("font_color_fg", "TabContainer", font_color); theme->set_color("font_color_bg", "TabContainer", font_color_disabled); theme->set_color("font_color_fg", "Tabs", font_color); diff --git a/editor/fileserver/editor_file_server.cpp b/editor/fileserver/editor_file_server.cpp index 3b402407df..2bea61fe04 100644 --- a/editor/fileserver/editor_file_server.cpp +++ b/editor/fileserver/editor_file_server.cpp @@ -80,9 +80,9 @@ void EditorFileServer::_subthread_start(void *s) { ERR_FAIL_COND(err != OK); } passutf8.write[passlen] = 0; - String s; - s.parse_utf8(passutf8.ptr()); - if (s != cd->efs->password) { + String s2; + s2.parse_utf8(passutf8.ptr()); + if (s2 != cd->efs->password) { encode_uint32(ERR_INVALID_DATA, buf4); cd->connection->put_data(buf4, 4); OS::get_singleton()->delay_usec(1000000); @@ -146,23 +146,23 @@ void EditorFileServer::_subthread_start(void *s) { ERR_FAIL_COND(err != OK); } fileutf8.write[namelen] = 0; - String s; - s.parse_utf8(fileutf8.ptr()); + String s2; + s2.parse_utf8(fileutf8.ptr()); if (cmd == FileAccessNetwork::COMMAND_FILE_EXISTS) { - print_verbose("FILE EXISTS: " + s); + print_verbose("FILE EXISTS: " + s2); } if (cmd == FileAccessNetwork::COMMAND_GET_MODTIME) { - print_verbose("MOD TIME: " + s); + print_verbose("MOD TIME: " + s2); } if (cmd == FileAccessNetwork::COMMAND_OPEN_FILE) { - print_verbose("OPEN: " + s); + print_verbose("OPEN: " + s2); } - if (!s.begins_with("res://")) { + if (!s2.begins_with("res://")) { _close_client(cd); - ERR_FAIL_COND(!s.begins_with("res://")); + ERR_FAIL_COND(!s2.begins_with("res://")); } ERR_CONTINUE(cd->files.has(id)); @@ -172,7 +172,7 @@ void EditorFileServer::_subthread_start(void *s) { cd->connection->put_data(buf4, 4); encode_uint32(FileAccessNetwork::RESPONSE_FILE_EXISTS, buf4); cd->connection->put_data(buf4, 4); - encode_uint32(FileAccess::exists(s), buf4); + encode_uint32(FileAccess::exists(s2), buf4); cd->connection->put_data(buf4, 4); DEBUG_TIME("open_file_end") break; @@ -184,13 +184,13 @@ void EditorFileServer::_subthread_start(void *s) { cd->connection->put_data(buf4, 4); encode_uint32(FileAccessNetwork::RESPONSE_GET_MODTIME, buf4); cd->connection->put_data(buf4, 4); - encode_uint64(FileAccess::get_modified_time(s), buf4); + encode_uint64(FileAccess::get_modified_time(s2), buf4); cd->connection->put_data(buf4, 8); DEBUG_TIME("open_file_end") break; } - FileAccess *fa = FileAccess::open(s, FileAccess::READ); + FileAccess *fa = FileAccess::open(s2, FileAccess::READ); if (!fa) { //not found, continue encode_uint32(id, buf4); diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index 1ac66fdd1d..b1aa75e124 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -90,7 +90,7 @@ bool FileSystemDock::_create_tree(TreeItem *p_parent, EditorFileSystemDirectory if (searched_string.length() > 0) { if (file_name.to_lower().find(searched_string) < 0) { - // The seached string is not in the file name, we skip it + // The searched string is not in the file name, we skip it continue; } else { // We expand all parents @@ -375,7 +375,7 @@ void FileSystemDock::_notification(int p_what) { // Update display of files in tree display_mode_setting = DisplayModeSetting(int(EditorSettings::get_singleton()->get("docks/filesystem/display_mode"))); - // Update allways showfolders + // Update always showfolders bool new_always_show_folders = bool(EditorSettings::get_singleton()->get("docks/filesystem/always_show_folders")); if (new_always_show_folders != always_show_folders) { always_show_folders = new_always_show_folders; @@ -1855,7 +1855,7 @@ void FileSystemDock::drop_data_fw(const Point2 &p_point, const Variant &p_data, // Drop on the favorite folder drop_position = 0; } else if (ti == resources_item) { - // Drop on the resouce item + // Drop on the resource item drop_position = dirs.size(); } else { // Drop in the list @@ -2157,7 +2157,7 @@ void FileSystemDock::select_file(const String &p_file) { void FileSystemDock::_file_multi_selected(int p_index, bool p_selected) { - // Set the path to the current focussed item + // Set the path to the current focused item int current = files->get_current(); if (current == p_index) { String fpath = files->get_item_metadata(current); diff --git a/editor/find_in_files.cpp b/editor/find_in_files.cpp index bae0d196fd..4dbba952bf 100644 --- a/editor/find_in_files.cpp +++ b/editor/find_in_files.cpp @@ -321,7 +321,7 @@ FindInFilesDialog::FindInFilesDialog() { _search_text_line_edit->connect("text_entered", this, "_on_search_text_entered"); gc->add_child(_search_text_line_edit); - gc->add_child(memnew(Control)); // Space to mantain the grid aligned. + gc->add_child(memnew(Control)); // Space to maintain the grid aligned. { HBoxContainer *hbc = memnew(HBoxContainer); @@ -766,9 +766,9 @@ void FindInFilesPanel::_on_replace_all_clicked() { if (!item->is_checked(0)) continue; - Map<TreeItem *, Result>::Element *E = _result_items.find(item); - ERR_FAIL_COND(E == NULL); - locations.push_back(E->value()); + Map<TreeItem *, Result>::Element *F = _result_items.find(item); + ERR_FAIL_COND(F == NULL); + locations.push_back(F->value()); } if (locations.size() != 0) { diff --git a/editor/import/editor_import_collada.cpp b/editor/import/editor_import_collada.cpp index dbf63102cf..652f1ebac9 100644 --- a/editor/import/editor_import_collada.cpp +++ b/editor/import/editor_import_collada.cpp @@ -724,13 +724,13 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<ArrayMesh> &p_me int _prim_ofs = 0; int vertidx = 0; - for (int p_i = 0; p_i < p.count; p_i++) { + for (int p_j = 0; p_j < p.count; p_j++) { int amount; if (p.polygons.size()) { - ERR_FAIL_INDEX_V(p_i, p.polygons.size(), ERR_INVALID_DATA); - amount = p.polygons[p_i]; + ERR_FAIL_INDEX_V(p_j, p.polygons.size(), ERR_INVALID_DATA); + amount = p.polygons[p_j]; } else { amount = 3; //triangles; } @@ -1100,7 +1100,7 @@ Error ColladaImport::_create_resources(Collada::Node *p_node, bool p_use_compres if (Object::cast_to<MeshInstance>(node)) { - Collada::NodeGeometry *ng = static_cast<Collada::NodeGeometry *>(p_node); + Collada::NodeGeometry *ng2 = static_cast<Collada::NodeGeometry *>(p_node); MeshInstance *mi = Object::cast_to<MeshInstance>(node); @@ -1113,16 +1113,16 @@ Error ColladaImport::_create_resources(Collada::Node *p_node, bool p_use_compres Vector<int> bone_remap; Vector<Ref<ArrayMesh> > morphs; - if (ng->controller) { + if (ng2->controller) { - String ngsource = ng->source; + String ngsource = ng2->source; if (collada.state.skin_controller_data_map.has(ngsource)) { ERR_FAIL_COND_V(!collada.state.skin_controller_data_map.has(ngsource), ERR_INVALID_DATA); skin = &collada.state.skin_controller_data_map[ngsource]; - Vector<String> skeletons = ng->skeletons; + Vector<String> skeletons = ng2->skeletons; ERR_FAIL_COND_V(skeletons.empty(), ERR_INVALID_DATA); @@ -1185,12 +1185,12 @@ Error ColladaImport::_create_resources(Collada::Node *p_node, bool p_use_compres Vector<String> names = morph->sources[target].sarray; for (int i = 0; i < names.size(); i++) { - String meshid = names[i]; - if (collada.state.mesh_data_map.has(meshid)) { + String meshid2 = names[i]; + if (collada.state.mesh_data_map.has(meshid2)) { Ref<ArrayMesh> mesh = Ref<ArrayMesh>(memnew(ArrayMesh)); - const Collada::MeshData &meshdata = collada.state.mesh_data_map[meshid]; + const Collada::MeshData &meshdata = collada.state.mesh_data_map[meshid2]; mesh->set_name(meshdata.name); - Error err = _create_mesh_surfaces(false, mesh, ng->material_map, meshdata, apply_xform, bone_remap, skin, NULL, Vector<Ref<ArrayMesh> >(), false); + Error err = _create_mesh_surfaces(false, mesh, ng2->material_map, meshdata, apply_xform, bone_remap, skin, NULL, Vector<Ref<ArrayMesh> >(), false); ERR_FAIL_COND_V(err, err); morphs.push_back(mesh); @@ -1212,7 +1212,7 @@ Error ColladaImport::_create_resources(Collada::Node *p_node, bool p_use_compres } } else { - meshid = ng->source; + meshid = ng2->source; } Ref<ArrayMesh> mesh; @@ -1226,7 +1226,7 @@ Error ColladaImport::_create_resources(Collada::Node *p_node, bool p_use_compres mesh = Ref<ArrayMesh>(memnew(ArrayMesh)); const Collada::MeshData &meshdata = collada.state.mesh_data_map[meshid]; mesh->set_name(meshdata.name); - Error err = _create_mesh_surfaces(morphs.size() == 0, mesh, ng->material_map, meshdata, apply_xform, bone_remap, skin, morph, morphs, p_use_compression, use_mesh_builtin_materials); + Error err = _create_mesh_surfaces(morphs.size() == 0, mesh, ng2->material_map, meshdata, apply_xform, bone_remap, skin, morph, morphs, p_use_compression, use_mesh_builtin_materials); ERR_FAIL_COND_V(err, err); mesh_cache[meshid] = mesh; @@ -1246,8 +1246,8 @@ Error ColladaImport::_create_resources(Collada::Node *p_node, bool p_use_compres String matname = meshdata.primitives[i].material; - if (ng->material_map.has(matname)) { - String target = ng->material_map[matname].target; + if (ng2->material_map.has(matname)) { + String target = ng2->material_map[matname].target; Ref<Material> material; if (!material_cache.has(target)) { @@ -1296,25 +1296,25 @@ Error ColladaImport::load(const String &p_path, int p_flags, bool p_force_make_t for (int i = 0; i < vs.root_nodes.size(); i++) { - Error err = _create_scene_skeletons(vs.root_nodes[i]); - if (err != OK) { + Error err2 = _create_scene_skeletons(vs.root_nodes[i]); + if (err2 != OK) { memdelete(scene); - ERR_FAIL_COND_V(err, err); + ERR_FAIL_COND_V(err2, err2); } } for (int i = 0; i < vs.root_nodes.size(); i++) { - Error err = _create_scene(vs.root_nodes[i], scene); - if (err != OK) { + Error err2 = _create_scene(vs.root_nodes[i], scene); + if (err2 != OK) { memdelete(scene); - ERR_FAIL_COND_V(err, err); + ERR_FAIL_COND_V(err2, err2); } - Error err2 = _create_resources(vs.root_nodes[i], p_use_compression); - if (err2 != OK) { + Error err3 = _create_resources(vs.root_nodes[i], p_use_compression); + if (err3 != OK) { memdelete(scene); - ERR_FAIL_COND_V(err2, err2); + ERR_FAIL_COND_V(err3, err3); } } @@ -1627,10 +1627,10 @@ void ColladaImport::create_animation(int p_clip, bool p_make_tracks_in_all_bones ERR_CONTINUE(xf.data.size() < 4); xf.data.write[3] = data[0]; } else if (at.component == "X" || at.component == "Y" || at.component == "Z") { - int cn = at.component[0] - 'X'; - ERR_CONTINUE(cn >= xf.data.size()); + int cn2 = at.component[0] - 'X'; + ERR_CONTINUE(cn2 >= xf.data.size()); ERR_CONTINUE(data.size() > 1); - xf.data.write[cn] = data[0]; + xf.data.write[cn2] = data[0]; } else if (data.size() == xf.data.size()) { xf.data = data; } else { @@ -1747,11 +1747,11 @@ void ColladaImport::create_animation(int p_clip, bool p_make_tracks_in_all_bones animation->track_set_path(track, path); animation->track_set_imported(track, true); //helps merging later - for (int i = 0; i < at.keys.size(); i++) { + for (int j = 0; j < at.keys.size(); j++) { - float time = at.keys[i].time; + float time = at.keys[j].time; Variant value; - Vector<float> data = at.keys[i].data; + Vector<float> data = at.keys[j].data; if (data.size() == 1) { //push a float value = data[0]; diff --git a/editor/import/editor_import_plugin.h b/editor/import/editor_import_plugin.h index 9e64fdb7c7..607d99e6e2 100644 --- a/editor/import/editor_import_plugin.h +++ b/editor/import/editor_import_plugin.h @@ -31,7 +31,7 @@ #ifndef EDITOR_IMPORT_PLUGIN_H #define EDITOR_IMPORT_PLUGIN_H -#include "core/io/resource_import.h" +#include "core/io/resource_importer.h" class EditorImportPlugin : public ResourceImporter { GDCLASS(EditorImportPlugin, Reference) diff --git a/editor/import/editor_scene_importer_gltf.cpp b/editor/import/editor_scene_importer_gltf.cpp index c29e9281fa..ff2f68ffd3 100644 --- a/editor/import/editor_scene_importer_gltf.cpp +++ b/editor/import/editor_scene_importer_gltf.cpp @@ -244,8 +244,8 @@ Error EditorSceneImporterGLTF::_parse_nodes(GLTFState &state) { if (n.has("children")) { Array children = n["children"]; - for (int i = 0; i < children.size(); i++) { - node->children.push_back(children[i]); + for (int j = 0; j < children.size(); j++) { + node->children.push_back(children[j]); } } @@ -879,7 +879,7 @@ Error EditorSceneImporterGLTF::_parse_meshes(GLTFState &state) { if (p.has("mode")) { int mode = p["mode"]; ERR_FAIL_INDEX_V(mode, 7, ERR_FILE_CORRUPT); - static const Mesh::PrimitiveType primitives[7] = { + static const Mesh::PrimitiveType primitives2[7] = { Mesh::PRIMITIVE_POINTS, Mesh::PRIMITIVE_LINES, Mesh::PRIMITIVE_LINE_LOOP, @@ -889,7 +889,7 @@ Error EditorSceneImporterGLTF::_parse_meshes(GLTFState &state) { Mesh::PRIMITIVE_TRIANGLE_FAN, }; - primitive = primitives[mode]; + primitive = primitives2[mode]; } if (a.has("POSITION")) { @@ -922,17 +922,17 @@ Error EditorSceneImporterGLTF::_parse_meshes(GLTFState &state) { //PoolVector<int> v = array[Mesh::ARRAY_BONES]; //PoolVector<int>::Read r = v.read(); - for (int j = 0; j < wc; j += 4) { + for (int k = 0; k < wc; k += 4) { float total = 0.0; - total += w[j + 0]; - total += w[j + 1]; - total += w[j + 2]; - total += w[j + 3]; + total += w[k + 0]; + total += w[k + 1]; + total += w[k + 2]; + total += w[k + 3]; if (total > 0.0) { - w[j + 0] /= total; - w[j + 1] /= total; - w[j + 2] /= total; - w[j + 3] /= total; + w[k + 0] /= total; + w[k + 1] /= total; + w[k + 2] /= total; + w[k + 3] /= total; } //print_verbose(itos(j / 4) + ": " + itos(r[j + 0]) + ":" + rtos(w[j + 0]) + ", " + itos(r[j + 1]) + ":" + rtos(w[j + 1]) + ", " + itos(r[j + 2]) + ":" + rtos(w[j + 2]) + ", " + itos(r[j + 3]) + ":" + rtos(w[j + 3])); @@ -950,8 +950,8 @@ Error EditorSceneImporterGLTF::_parse_meshes(GLTFState &state) { int is = indices.size(); PoolVector<int>::Write w = indices.write(); - for (int i = 0; i < is; i += 3) { - SWAP(w[i + 1], w[i + 2]); + for (int k = 0; k < is; k += 3) { + SWAP(w[k + 1], w[k + 2]); } } array[Mesh::ARRAY_INDEX] = indices; @@ -964,10 +964,10 @@ Error EditorSceneImporterGLTF::_parse_meshes(GLTFState &state) { indices.resize(vs); { PoolVector<int>::Write w = indices.write(); - for (int i = 0; i < vs; i += 3) { - w[i] = i; - w[i + 1] = i + 2; - w[i + 2] = i + 1; + for (int k = 0; k < vs; k += 3) { + w[k] = k; + w[k + 1] = k + 2; + w[k + 2] = k + 1; } } array[Mesh::ARRAY_INDEX] = indices; diff --git a/editor/import/resource_importer_bitmask.cpp b/editor/import/resource_importer_bitmask.cpp index 431396d584..b568cbda9b 100644 --- a/editor/import/resource_importer_bitmask.cpp +++ b/editor/import/resource_importer_bitmask.cpp @@ -34,7 +34,7 @@ #include "core/io/image_loader.h" #include "editor/editor_file_system.h" #include "editor/editor_node.h" -#include "scene/resources/bit_mask.h" +#include "scene/resources/bit_map.h" #include "scene/resources/texture.h" String ResourceImporterBitMap::get_importer_name() const { diff --git a/editor/import/resource_importer_bitmask.h b/editor/import/resource_importer_bitmask.h index b0168e2b53..7cfb0c4a98 100644 --- a/editor/import/resource_importer_bitmask.h +++ b/editor/import/resource_importer_bitmask.h @@ -32,7 +32,7 @@ #define RESOURCE_IMPORTER_BITMASK_H #include "core/image.h" -#include "core/io/resource_import.h" +#include "core/io/resource_importer.h" class StreamBitMap; diff --git a/editor/import/resource_importer_csv_translation.h b/editor/import/resource_importer_csv_translation.h index 3d74731e8c..cf16826535 100644 --- a/editor/import/resource_importer_csv_translation.h +++ b/editor/import/resource_importer_csv_translation.h @@ -31,7 +31,7 @@ #ifndef RESOURCEIMPORTERCSVTRANSLATION_H #define RESOURCEIMPORTERCSVTRANSLATION_H -#include "core/io/resource_import.h" +#include "core/io/resource_importer.h" class ResourceImporterCSVTranslation : public ResourceImporter { GDCLASS(ResourceImporterCSVTranslation, ResourceImporter) diff --git a/editor/import/resource_importer_image.h b/editor/import/resource_importer_image.h index b38d833c5b..ffe05bdf58 100644 --- a/editor/import/resource_importer_image.h +++ b/editor/import/resource_importer_image.h @@ -32,7 +32,7 @@ #define RESOURCE_IMPORTER_IMAGE_H #include "core/image.h" -#include "core/io/resource_import.h" +#include "core/io/resource_importer.h" class ResourceImporterImage : public ResourceImporter { GDCLASS(ResourceImporterImage, ResourceImporter) diff --git a/editor/import/resource_importer_layered_texture.cpp b/editor/import/resource_importer_layered_texture.cpp index f43df02916..e38265b619 100644 --- a/editor/import/resource_importer_layered_texture.cpp +++ b/editor/import/resource_importer_layered_texture.cpp @@ -132,9 +132,9 @@ void ResourceImporterLayeredTexture::_save_tex(const Vector<Ref<Image> > &p_imag int mmc = image->get_mipmap_count() + 1; f->store_32(mmc); - for (int i = 0; i < mmc; i++) { + for (int j = 0; j < mmc; j++) { - if (i > 0) { + if (j > 0) { image->shrink_x2(); } diff --git a/editor/import/resource_importer_layered_texture.h b/editor/import/resource_importer_layered_texture.h index 599fdf12fa..6a616e09d6 100644 --- a/editor/import/resource_importer_layered_texture.h +++ b/editor/import/resource_importer_layered_texture.h @@ -32,7 +32,7 @@ #define RESOURCE_IMPORTER_LAYERED_TEXTURE_H #include "core/image.h" -#include "core/io/resource_import.h" +#include "core/io/resource_importer.h" class StreamTexture; diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp index f230fa1b8b..ad436b2797 100644 --- a/editor/import/resource_importer_scene.cpp +++ b/editor/import/resource_importer_scene.cpp @@ -46,7 +46,7 @@ #include "scene/resources/box_shape.h" #include "scene/resources/plane_shape.h" #include "scene/resources/ray_shape.h" -#include "scene/resources/scene_format_text.h" +#include "scene/resources/resource_format_text.h" #include "scene/resources/sphere_shape.h" uint32_t EditorSceneImporter::get_import_flags() const { @@ -1314,9 +1314,9 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p if (bool(p_options["external_files/store_in_subdir"])) { String subdir_name = p_source_file.get_file().get_basename(); DirAccess *da = DirAccess::open(base_path); - Error err = da->make_dir(subdir_name); + Error err2 = da->make_dir(subdir_name); memdelete(da); - ERR_FAIL_COND_V(err != OK && err != ERR_ALREADY_EXISTS, err); + ERR_FAIL_COND_V(err2 != OK && err2 != ERR_ALREADY_EXISTS, err2); base_path = base_path.plus_file(subdir_name); } } @@ -1331,7 +1331,7 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p float texel_size = p_options["meshes/lightmap_texel_size"]; texel_size = MAX(0.001, texel_size); - EditorProgress progress("gen_lightmaps", TTR("Generating Lightmaps"), meshes.size()); + EditorProgress progress2("gen_lightmaps", TTR("Generating Lightmaps"), meshes.size()); int step = 0; for (Map<Ref<ArrayMesh>, Transform>::Element *E = meshes.front(); E; E = E->next()) { @@ -1341,10 +1341,10 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p name = "Mesh " + itos(step); } - progress.step(TTR("Generating for Mesh: ") + name + " (" + itos(step) + "/" + itos(meshes.size()) + ")", step); + progress2.step(TTR("Generating for Mesh: ") + name + " (" + itos(step) + "/" + itos(meshes.size()) + ")", step); - Error err = mesh->lightmap_unwrap(E->get(), texel_size); - if (err != OK) { + Error err2 = mesh->lightmap_unwrap(E->get(), texel_size); + if (err2 != OK) { EditorNode::add_io_error("Mesh '" + name + "' failed lightmap generation. Please fix geometry."); } step++; diff --git a/editor/import/resource_importer_scene.h b/editor/import/resource_importer_scene.h index 9435b6599a..9d06b411d6 100644 --- a/editor/import/resource_importer_scene.h +++ b/editor/import/resource_importer_scene.h @@ -31,7 +31,7 @@ #ifndef RESOURCEIMPORTERSCENE_H #define RESOURCEIMPORTERSCENE_H -#include "core/io/resource_import.h" +#include "core/io/resource_importer.h" #include "scene/resources/animation.h" #include "scene/resources/mesh.h" #include "scene/resources/shape.h" diff --git a/editor/import/resource_importer_texture.h b/editor/import/resource_importer_texture.h index 900654c114..408af1edcf 100644 --- a/editor/import/resource_importer_texture.h +++ b/editor/import/resource_importer_texture.h @@ -32,7 +32,7 @@ #define RESOURCEIMPORTTEXTURE_H #include "core/image.h" -#include "core/io/resource_import.h" +#include "core/io/resource_importer.h" class StreamTexture; diff --git a/editor/import/resource_importer_wav.h b/editor/import/resource_importer_wav.h index 68e677b977..755dea3d84 100644 --- a/editor/import/resource_importer_wav.h +++ b/editor/import/resource_importer_wav.h @@ -31,7 +31,7 @@ #ifndef RESOURCEIMPORTWAV_H #define RESOURCEIMPORTWAV_H -#include "core/io/resource_import.h" +#include "core/io/resource_importer.h" class ResourceImporterWAV : public ResourceImporter { GDCLASS(ResourceImporterWAV, ResourceImporter) diff --git a/editor/import_dock.cpp b/editor/import_dock.cpp index 40cf02ac9d..15539ee3db 100644 --- a/editor/import_dock.cpp +++ b/editor/import_dock.cpp @@ -424,7 +424,7 @@ void ImportDock::_reimport_attempt() { void ImportDock::_reimport_and_restart() { EditorNode::get_singleton()->save_all_scenes(); - EditorResourcePreview::get_singleton()->stop(); //dont try to re-create previews after import + EditorResourcePreview::get_singleton()->stop(); //don't try to re-create previews after import _reimport(); EditorNode::get_singleton()->restart_editor(); } diff --git a/editor/import_dock.h b/editor/import_dock.h index 1d43e00b63..77a34e80eb 100644 --- a/editor/import_dock.h +++ b/editor/import_dock.h @@ -32,7 +32,7 @@ #define IMPORTDOCK_H #include "core/io/config_file.h" -#include "core/io/resource_import.h" +#include "core/io/resource_importer.h" #include "editor/editor_file_system.h" #include "editor/editor_inspector.h" #include "scene/gui/box_container.h" diff --git a/editor/plugin_config_dialog.cpp b/editor/plugin_config_dialog.cpp index 88672bdf34..12bf544357 100644 --- a/editor/plugin_config_dialog.cpp +++ b/editor/plugin_config_dialog.cpp @@ -120,6 +120,10 @@ void PluginConfigDialog::_notification(int p_what) { connect("confirmed", this, "_on_confirmed"); get_cancel()->connect("pressed", this, "_on_cancelled"); } break; + + case NOTIFICATION_POST_POPUP: { + name_edit->grab_focus(); + } break; } } @@ -215,11 +219,15 @@ PluginConfigDialog::PluginConfigDialog() { grid->add_child(script_option_lb); script_option_edit = memnew(OptionButton); + int default_lang = 0; for (int i = 0; i < ScriptServer::get_language_count(); i++) { ScriptLanguage *lang = ScriptServer::get_language(i); script_option_edit->add_item(lang->get_name()); + if (lang == GDScriptLanguage::get_singleton()) { + default_lang = i; + } } - script_option_edit->select(0); + script_option_edit->select(default_lang); grid->add_child(script_option_edit); Label *script_lb = memnew(Label); diff --git a/editor/plugins/abstract_polygon_2d_editor.cpp b/editor/plugins/abstract_polygon_2d_editor.cpp index 41e2062ab2..28f786e99a 100644 --- a/editor/plugins/abstract_polygon_2d_editor.cpp +++ b/editor/plugins/abstract_polygon_2d_editor.cpp @@ -201,6 +201,8 @@ void AbstractPolygon2DEditor::_notification(int p_what) { case NOTIFICATION_READY: { + disable_polygon_editing(false, String()); + button_create->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("CurveCreate", "EditorIcons")); button_edit->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("CurveEdit", "EditorIcons")); button_delete->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("CurveDelete", "EditorIcons")); @@ -275,9 +277,30 @@ void AbstractPolygon2DEditor::_wip_close() { selected_point = Vertex(); } +void AbstractPolygon2DEditor::disable_polygon_editing(bool p_disable, String p_reason) { + + _polygon_editing_enabled = !p_disable; + + button_create->set_disabled(p_disable); + button_edit->set_disabled(p_disable); + button_delete->set_disabled(p_disable); + + if (p_disable) { + + button_create->set_tooltip(p_reason); + button_edit->set_tooltip(p_reason); + button_delete->set_tooltip(p_reason); + } else { + + button_create->set_tooltip(TTR("Create points.")); + button_edit->set_tooltip(TTR("Edit points.\nLMB: Move Point\nRMB: Erase Point")); + button_delete->set_tooltip(TTR("Erase points.")); + } +} + bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { - if (!_get_node()) + if (!_get_node() || !_polygon_editing_enabled) return false; Ref<InputEventMouseButton> mb = p_event; @@ -324,16 +347,16 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) return true; } else { - Vector<Vector2> vertices = _get_polygon(insert.polygon); - pre_move_edit = vertices; + Vector<Vector2> vertices2 = _get_polygon(insert.polygon); + pre_move_edit = vertices2; printf("setting pre_move_edit\n"); edited_point = PosVertex(insert.polygon, insert.vertex + 1, xform.affine_inverse().xform(insert.pos)); - vertices.insert(edited_point.vertex, edited_point.pos); + vertices2.insert(edited_point.vertex, edited_point.pos); selected_point = edited_point; edge_point = PosVertex(); undo_redo->create_action(TTR("Insert Point")); - _action_set_polygon(insert.polygon, vertices); + _action_set_polygon(insert.polygon, vertices2); _commit_action(); return true; } @@ -627,9 +650,8 @@ void AbstractPolygon2DEditor::forward_canvas_draw_over_viewport(Control *p_overl void AbstractPolygon2DEditor::edit(Node *p_polygon) { - if (!canvas_item_editor) { + if (!canvas_item_editor) canvas_item_editor = CanvasItemEditor::get_singleton(); - } if (p_polygon) { @@ -648,7 +670,6 @@ void AbstractPolygon2DEditor::edit(Node *p_polygon) { selected_point = Vertex(); canvas_item_editor->update_viewport(); - } else { _set_node(NULL); @@ -783,19 +804,16 @@ AbstractPolygon2DEditor::AbstractPolygon2DEditor(EditorNode *p_editor, bool p_wi add_child(button_create); button_create->connect("pressed", this, "_menu_option", varray(MODE_CREATE)); button_create->set_toggle_mode(true); - button_create->set_tooltip(TTR("Create points.")); button_edit = memnew(ToolButton); add_child(button_edit); button_edit->connect("pressed", this, "_menu_option", varray(MODE_EDIT)); button_edit->set_toggle_mode(true); - button_edit->set_tooltip(TTR("Edit points.\nLMB: Move Point\nRMB: Erase Point")); button_delete = memnew(ToolButton); add_child(button_delete); button_delete->connect("pressed", this, "_menu_option", varray(MODE_DELETE)); button_delete->set_toggle_mode(true); - button_delete->set_tooltip(TTR("Erase points.")); create_resource = memnew(ConfirmationDialog); add_child(create_resource); diff --git a/editor/plugins/abstract_polygon_2d_editor.h b/editor/plugins/abstract_polygon_2d_editor.h index 289c2785b1..97244fa4e9 100644 --- a/editor/plugins/abstract_polygon_2d_editor.h +++ b/editor/plugins/abstract_polygon_2d_editor.h @@ -81,6 +81,8 @@ class AbstractPolygon2DEditor : public HBoxContainer { bool wip_active; bool wip_destructive; + bool _polygon_editing_enabled; + CanvasItemEditor *canvas_item_editor; EditorNode *editor; Panel *panel; @@ -135,6 +137,8 @@ protected: virtual void _create_resource(); public: + void disable_polygon_editing(bool p_disable, String p_reason); + bool forward_gui_input(const Ref<InputEvent> &p_event); void forward_canvas_draw_over_viewport(Control *p_overlay); diff --git a/editor/plugins/animation_blend_space_1d_editor.cpp b/editor/plugins/animation_blend_space_1d_editor.cpp index 3029ad978a..2ae39d90de 100644 --- a/editor/plugins/animation_blend_space_1d_editor.cpp +++ b/editor/plugins/animation_blend_space_1d_editor.cpp @@ -142,7 +142,7 @@ void AnimationNodeBlendSpace1DEditor::_blend_space_gui_input(const Ref<InputEven } updating = true; - undo_redo->create_action("Move Node Point"); + undo_redo->create_action(TTR("Move Node Point")); undo_redo->add_do_method(blend_space.ptr(), "set_blend_point_position", selected_point, point); undo_redo->add_undo_method(blend_space.ptr(), "set_blend_point_position", selected_point, blend_space->get_blend_point_position(selected_point)); undo_redo->add_do_method(this, "_update_space"); @@ -325,7 +325,7 @@ void AnimationNodeBlendSpace1DEditor::_config_changed(double) { return; updating = true; - undo_redo->create_action("Change BlendSpace1D Limits"); + undo_redo->create_action(TTR("Change BlendSpace1D Limits")); undo_redo->add_do_method(blend_space.ptr(), "set_max_space", max_value->get_value()); undo_redo->add_undo_method(blend_space.ptr(), "set_max_space", blend_space->get_max_space()); undo_redo->add_do_method(blend_space.ptr(), "set_min_space", min_value->get_value()); @@ -345,7 +345,7 @@ void AnimationNodeBlendSpace1DEditor::_labels_changed(String) { return; updating = true; - undo_redo->create_action("Change BlendSpace1D Labels", UndoRedo::MERGE_ENDS); + undo_redo->create_action(TTR("Change BlendSpace1D Labels"), UndoRedo::MERGE_ENDS); undo_redo->add_do_method(blend_space.ptr(), "set_value_label", label_value->get_text()); undo_redo->add_undo_method(blend_space.ptr(), "set_value_label", blend_space->get_value_label()); undo_redo->add_do_method(this, "_update_space"); @@ -401,7 +401,7 @@ void AnimationNodeBlendSpace1DEditor::_add_menu_type(int p_index) { } updating = true; - undo_redo->create_action("Add Node Point"); + undo_redo->create_action(TTR("Add Node Point")); undo_redo->add_do_method(blend_space.ptr(), "add_blend_point", node, add_point_pos); undo_redo->add_undo_method(blend_space.ptr(), "remove_blend_point", blend_space->get_blend_point_count()); undo_redo->add_do_method(this, "_update_space"); @@ -419,7 +419,7 @@ void AnimationNodeBlendSpace1DEditor::_add_animation_type(int p_index) { anim->set_animation(animations_to_add[p_index]); updating = true; - undo_redo->create_action("Add Animation Point"); + undo_redo->create_action(TTR("Add Animation Point")); undo_redo->add_do_method(blend_space.ptr(), "add_blend_point", anim, add_point_pos); undo_redo->add_undo_method(blend_space.ptr(), "remove_blend_point", blend_space->get_blend_point_count()); undo_redo->add_do_method(this, "_update_space"); @@ -489,7 +489,7 @@ void AnimationNodeBlendSpace1DEditor::_erase_selected() { if (selected_point != -1) { updating = true; - undo_redo->create_action("Remove BlendSpace1D Point"); + undo_redo->create_action(TTR("Remove BlendSpace1D Point")); undo_redo->add_do_method(blend_space.ptr(), "remove_blend_point", selected_point); undo_redo->add_undo_method(blend_space.ptr(), "add_blend_point", blend_space->get_blend_point_node(selected_point), blend_space->get_blend_point_position(selected_point), selected_point); undo_redo->add_do_method(this, "_update_space"); @@ -507,7 +507,7 @@ void AnimationNodeBlendSpace1DEditor::_edit_point_pos(double) { return; updating = true; - undo_redo->create_action("Move BlendSpace1D Node Point"); + undo_redo->create_action(TTR("Move BlendSpace1D Node Point")); undo_redo->add_do_method(blend_space.ptr(), "set_blend_point_position", selected_point, edit_value->get_value()); undo_redo->add_undo_method(blend_space.ptr(), "set_blend_point_position", selected_point, blend_space->get_blend_point_position(selected_point)); undo_redo->add_do_method(this, "_update_space"); diff --git a/editor/plugins/animation_blend_space_2d_editor.cpp b/editor/plugins/animation_blend_space_2d_editor.cpp index 038e2d0b3e..918f3a2149 100644 --- a/editor/plugins/animation_blend_space_2d_editor.cpp +++ b/editor/plugins/animation_blend_space_2d_editor.cpp @@ -200,7 +200,7 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_gui_input(const Ref<InputEven } updating = true; - undo_redo->create_action("Add Triangle"); + undo_redo->create_action(TTR("Add Triangle")); undo_redo->add_do_method(blend_space.ptr(), "add_triangle", making_triangle[0], making_triangle[1], making_triangle[2]); undo_redo->add_undo_method(blend_space.ptr(), "remove_triangle", blend_space->get_triangle_count()); undo_redo->add_do_method(this, "_update_space"); @@ -225,7 +225,7 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_gui_input(const Ref<InputEven } updating = true; - undo_redo->create_action("Move Node Point"); + undo_redo->create_action(TTR("Move Node Point")); undo_redo->add_do_method(blend_space.ptr(), "set_blend_point_position", selected_point, point); undo_redo->add_undo_method(blend_space.ptr(), "set_blend_point_position", selected_point, blend_space->get_blend_point_position(selected_point)); undo_redo->add_do_method(this, "_update_space"); @@ -333,7 +333,7 @@ void AnimationNodeBlendSpace2DEditor::_add_menu_type(int p_index) { } updating = true; - undo_redo->create_action("Add Node Point"); + undo_redo->create_action(TTR("Add Node Point")); undo_redo->add_do_method(blend_space.ptr(), "add_blend_point", node, add_point_pos); undo_redo->add_undo_method(blend_space.ptr(), "remove_blend_point", blend_space->get_blend_point_count()); undo_redo->add_do_method(this, "_update_space"); @@ -352,7 +352,7 @@ void AnimationNodeBlendSpace2DEditor::_add_animation_type(int p_index) { anim->set_animation(animations_to_add[p_index]); updating = true; - undo_redo->create_action("Add Animation Point"); + undo_redo->create_action(TTR("Add Animation Point")); undo_redo->add_do_method(blend_space.ptr(), "add_blend_point", anim, add_point_pos); undo_redo->add_undo_method(blend_space.ptr(), "remove_blend_point", blend_space->get_blend_point_count()); undo_redo->add_do_method(this, "_update_space"); @@ -639,7 +639,7 @@ void AnimationNodeBlendSpace2DEditor::_config_changed(double) { return; updating = true; - undo_redo->create_action("Change BlendSpace2D Limits"); + undo_redo->create_action(TTR("Change BlendSpace2D Limits")); undo_redo->add_do_method(blend_space.ptr(), "set_max_space", Vector2(max_x_value->get_value(), max_y_value->get_value())); undo_redo->add_undo_method(blend_space.ptr(), "set_max_space", blend_space->get_max_space()); undo_redo->add_do_method(blend_space.ptr(), "set_min_space", Vector2(min_x_value->get_value(), min_y_value->get_value())); @@ -661,7 +661,7 @@ void AnimationNodeBlendSpace2DEditor::_labels_changed(String) { return; updating = true; - undo_redo->create_action("Change BlendSpace2D Labels", UndoRedo::MERGE_ENDS); + undo_redo->create_action(TTR("Change BlendSpace2D Labels"), UndoRedo::MERGE_ENDS); undo_redo->add_do_method(blend_space.ptr(), "set_x_label", label_x->get_text()); undo_redo->add_undo_method(blend_space.ptr(), "set_x_label", blend_space->get_x_label()); undo_redo->add_do_method(blend_space.ptr(), "set_y_label", label_y->get_text()); @@ -677,7 +677,7 @@ void AnimationNodeBlendSpace2DEditor::_erase_selected() { if (selected_point != -1) { updating = true; - undo_redo->create_action("Remove BlendSpace2D Point"); + undo_redo->create_action(TTR("Remove BlendSpace2D Point")); undo_redo->add_do_method(blend_space.ptr(), "remove_blend_point", selected_point); undo_redo->add_undo_method(blend_space.ptr(), "add_blend_point", blend_space->get_blend_point_node(selected_point), blend_space->get_blend_point_position(selected_point), selected_point); @@ -700,7 +700,7 @@ void AnimationNodeBlendSpace2DEditor::_erase_selected() { } else if (selected_triangle != -1) { updating = true; - undo_redo->create_action("Remove BlendSpace2D Triangle"); + undo_redo->create_action(TTR("Remove BlendSpace2D Triangle")); undo_redo->add_do_method(blend_space.ptr(), "remove_triangle", selected_triangle); undo_redo->add_undo_method(blend_space.ptr(), "add_triangle", blend_space->get_triangle_point(selected_triangle, 0), blend_space->get_triangle_point(selected_triangle, 1), blend_space->get_triangle_point(selected_triangle, 2), selected_triangle); @@ -737,7 +737,7 @@ void AnimationNodeBlendSpace2DEditor::_edit_point_pos(double) { if (updating) return; updating = true; - undo_redo->create_action("Move Node Point"); + undo_redo->create_action(TTR("Move Node Point")); undo_redo->add_do_method(blend_space.ptr(), "set_blend_point_position", selected_point, Vector2(edit_x->get_value(), edit_y->get_value())); undo_redo->add_undo_method(blend_space.ptr(), "set_blend_point_position", selected_point, blend_space->get_blend_point_position(selected_point)); undo_redo->add_do_method(this, "_update_space"); @@ -814,7 +814,7 @@ void AnimationNodeBlendSpace2DEditor::_removed_from_graph() { void AnimationNodeBlendSpace2DEditor::_auto_triangles_toggled() { - undo_redo->create_action("Toggle Auto Triangles"); + undo_redo->create_action(TTR("Toggle Auto Triangles")); undo_redo->add_do_method(blend_space.ptr(), "set_auto_triangles", auto_triangles->is_pressed()); undo_redo->add_undo_method(blend_space.ptr(), "set_auto_triangles", blend_space->get_auto_triangles()); undo_redo->add_do_method(this, "_update_space"); diff --git a/editor/plugins/animation_blend_tree_editor_plugin.cpp b/editor/plugins/animation_blend_tree_editor_plugin.cpp index 13c80e5394..eef3358260 100644 --- a/editor/plugins/animation_blend_tree_editor_plugin.cpp +++ b/editor/plugins/animation_blend_tree_editor_plugin.cpp @@ -91,7 +91,7 @@ void AnimationNodeBlendTreeEditor::_property_changed(const StringName &p_propert AnimationTree *tree = AnimationTreeEditor::get_singleton()->get_tree(); updating = true; - undo_redo->create_action("Parameter Changed: " + String(p_property), UndoRedo::MERGE_ENDS); + undo_redo->create_action(TTR("Parameter Changed") + ": " + String(p_property), UndoRedo::MERGE_ENDS); undo_redo->add_do_property(tree, p_property, p_value); undo_redo->add_undo_property(tree, p_property, tree->get(p_property)); undo_redo->add_do_method(this, "_update_graph"); @@ -325,7 +325,7 @@ void AnimationNodeBlendTreeEditor::_add_node(int p_idx) { name = base_name + " " + itos(base); } - undo_redo->create_action("Add Node to BlendTree"); + undo_redo->create_action(TTR("Add Node to BlendTree")); undo_redo->add_do_method(blend_tree.ptr(), "add_node", name, anode, instance_pos / EDSCALE); undo_redo->add_undo_method(blend_tree.ptr(), "remove_node", name); undo_redo->add_do_method(this, "_update_graph"); @@ -336,7 +336,7 @@ void AnimationNodeBlendTreeEditor::_add_node(int p_idx) { void AnimationNodeBlendTreeEditor::_node_dragged(const Vector2 &p_from, const Vector2 &p_to, const StringName &p_which) { updating = true; - undo_redo->create_action("Node Moved"); + undo_redo->create_action(TTR("Node Moved")); undo_redo->add_do_method(blend_tree.ptr(), "set_node_position", p_which, p_to / EDSCALE); undo_redo->add_undo_method(blend_tree.ptr(), "set_node_position", p_which, p_from / EDSCALE); undo_redo->add_do_method(this, "_update_graph"); @@ -354,7 +354,7 @@ void AnimationNodeBlendTreeEditor::_connection_request(const String &p_from, int return; } - undo_redo->create_action("Nodes Connected"); + undo_redo->create_action(TTR("Nodes Connected")); undo_redo->add_do_method(blend_tree.ptr(), "connect_node", p_to, p_to_index, p_from); undo_redo->add_undo_method(blend_tree.ptr(), "disconnect_node", p_to, p_to_index); undo_redo->add_do_method(this, "_update_graph"); @@ -367,7 +367,7 @@ void AnimationNodeBlendTreeEditor::_disconnection_request(const String &p_from, graph->disconnect_node(p_from, p_from_index, p_to, p_to_index); updating = true; - undo_redo->create_action("Nodes Disconnected"); + undo_redo->create_action(TTR("Nodes Disconnected")); undo_redo->add_do_method(blend_tree.ptr(), "disconnect_node", p_to, p_to_index); undo_redo->add_undo_method(blend_tree.ptr(), "connect_node", p_to, p_to_index, p_from); undo_redo->add_do_method(this, "_update_graph"); @@ -383,7 +383,7 @@ void AnimationNodeBlendTreeEditor::_anim_selected(int p_index, Array p_options, Ref<AnimationNodeAnimation> anim = blend_tree->get_node(p_node); ERR_FAIL_COND(!anim.is_valid()); - undo_redo->create_action("Set Animation"); + undo_redo->create_action(TTR("Set Animation")); undo_redo->add_do_method(anim.ptr(), "set_animation", option); undo_redo->add_undo_method(anim.ptr(), "set_animation", anim->get_animation()); undo_redo->add_do_method(this, "_update_graph"); @@ -393,7 +393,7 @@ void AnimationNodeBlendTreeEditor::_anim_selected(int p_index, Array p_options, void AnimationNodeBlendTreeEditor::_delete_request(const String &p_which) { - undo_redo->create_action("Delete Node"); + undo_redo->create_action(TTR("Delete Node")); undo_redo->add_do_method(blend_tree.ptr(), "remove_node", p_which); undo_redo->add_undo_method(blend_tree.ptr(), "add_node", p_which, blend_tree->get_node(p_which), blend_tree.ptr()->get_node_position(p_which)); @@ -434,7 +434,7 @@ void AnimationNodeBlendTreeEditor::_open_in_editor(const String &p_which) { void AnimationNodeBlendTreeEditor::_filter_toggled() { updating = true; - undo_redo->create_action("Toggle filter on/off"); + undo_redo->create_action(TTR("Toggle Filter On/Off")); undo_redo->add_do_method(_filter_edit.ptr(), "set_filter_enabled", filter_enabled->is_pressed()); undo_redo->add_undo_method(_filter_edit.ptr(), "set_filter_enabled", _filter_edit->is_filter_enabled()); undo_redo->add_do_method(this, "_update_filters", _filter_edit); @@ -452,7 +452,7 @@ void AnimationNodeBlendTreeEditor::_filter_edited() { bool filtered = edited->is_checked(0); updating = true; - undo_redo->create_action("Change filter"); + undo_redo->create_action(TTR("Change Filter")); undo_redo->add_do_method(_filter_edit.ptr(), "set_filter_path", edited_path, filtered); undo_redo->add_undo_method(_filter_edit.ptr(), "set_filter_path", edited_path, _filter_edit->is_path_filtered(edited_path)); undo_redo->add_do_method(this, "_update_filters", _filter_edit); @@ -769,7 +769,7 @@ void AnimationNodeBlendTreeEditor::_node_renamed(const String &p_text, Ref<Anima String base_path = AnimationTreeEditor::get_singleton()->get_base_path(); updating = true; - undo_redo->create_action("Node Renamed"); + undo_redo->create_action(TTR("Node Renamed")); undo_redo->add_do_method(blend_tree.ptr(), "rename_node", prev_name, name); undo_redo->add_undo_method(blend_tree.ptr(), "rename_node", name, prev_name); undo_redo->add_do_method(AnimationTreeEditor::get_singleton()->get_tree(), "rename_parameter", base_path + prev_name, base_path + name); @@ -785,8 +785,8 @@ void AnimationNodeBlendTreeEditor::_node_renamed(const String &p_text, Ref<Anima for (int i = 0; i < visible_properties.size(); i++) { String pname = visible_properties[i]->get_edited_property().operator String(); if (pname.begins_with(base_path + prev_name)) { - String new_name = pname.replace_first(base_path + prev_name, base_path + name); - visible_properties[i]->set_object_and_property(visible_properties[i]->get_edited_object(), new_name); + String new_name2 = pname.replace_first(base_path + prev_name, base_path + name); + visible_properties[i]->set_object_and_property(visible_properties[i]->get_edited_object(), new_name2); } } diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp index b32b537d3d..bbaf41e3cc 100644 --- a/editor/plugins/animation_player_editor_plugin.cpp +++ b/editor/plugins/animation_player_editor_plugin.cpp @@ -1160,22 +1160,22 @@ void AnimationPlayerEditor::_animation_tool_menu(int p_option) { return; } - String current = animation->get_item_text(animation->get_selected()); - Ref<Animation> anim = player->get_animation(current); - //editor->edit_resource(anim); - EditorSettings::get_singleton()->set_resource_clipboard(anim); + String current2 = animation->get_item_text(animation->get_selected()); + Ref<Animation> anim2 = player->get_animation(current2); + //editor->edit_resource(anim2); + EditorSettings::get_singleton()->set_resource_clipboard(anim2); } break; case TOOL_PASTE_ANIM: { - Ref<Animation> anim = EditorSettings::get_singleton()->get_resource_clipboard(); - if (!anim.is_valid()) { + Ref<Animation> anim2 = EditorSettings::get_singleton()->get_resource_clipboard(); + if (!anim2.is_valid()) { error_dialog->set_text(TTR("No animation resource on clipboard!")); error_dialog->popup_centered_minsize(); return; } - String name = anim->get_name(); + String name = anim2->get_name(); if (name == "") { name = TTR("Pasted Animation"); } @@ -1189,7 +1189,7 @@ void AnimationPlayerEditor::_animation_tool_menu(int p_option) { } undo_redo->create_action(TTR("Paste Animation")); - undo_redo->add_do_method(player, "add_animation", name, anim); + undo_redo->add_do_method(player, "add_animation", name, anim2); undo_redo->add_undo_method(player, "remove_animation", name); undo_redo->add_do_method(this, "_animation_player_changed", player); undo_redo->add_undo_method(this, "_animation_player_changed", player); @@ -1206,9 +1206,9 @@ void AnimationPlayerEditor::_animation_tool_menu(int p_option) { return; } - String current = animation->get_item_text(animation->get_selected()); - Ref<Animation> anim = player->get_animation(current); - editor->edit_resource(anim); + String current2 = animation->get_item_text(animation->get_selected()); + Ref<Animation> anim2 = player->get_animation(current2); + editor->edit_resource(anim2); } break; } diff --git a/editor/plugins/animation_state_machine_editor.cpp b/editor/plugins/animation_state_machine_editor.cpp index 197ee77254..cb3e5a8129 100644 --- a/editor/plugins/animation_state_machine_editor.cpp +++ b/editor/plugins/animation_state_machine_editor.cpp @@ -226,7 +226,7 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv Ref<AnimationNode> an = state_machine->get_node(selected_node); updating = true; - undo_redo->create_action("Move Node"); + undo_redo->create_action(TTR("Move Node")); undo_redo->add_do_method(state_machine.ptr(), "set_node_position", selected_node, state_machine->get_node_position(selected_node) + drag_ofs / EDSCALE); undo_redo->add_undo_method(state_machine.ptr(), "set_node_position", selected_node, state_machine->get_node_position(selected_node)); undo_redo->add_do_method(this, "_update_graph"); @@ -271,7 +271,7 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv tr->set_switch_mode(AnimationNodeStateMachineTransition::SwitchMode(transition_mode->get_selected())); updating = true; - undo_redo->create_action("Add Transition"); + undo_redo->create_action(TTR("Add Transition")); undo_redo->add_do_method(state_machine.ptr(), "add_transition", connecting_from, connecting_to_node, tr); undo_redo->add_undo_method(state_machine.ptr(), "remove_transition", connecting_from, connecting_to_node); undo_redo->add_do_method(this, "_update_graph"); @@ -463,7 +463,7 @@ void AnimationNodeStateMachineEditor::_add_menu_type(int p_index) { } updating = true; - undo_redo->create_action("Add Node"); + undo_redo->create_action(TTR("Add Node")); undo_redo->add_do_method(state_machine.ptr(), "add_node", name, node, add_node_pos); undo_redo->add_undo_method(state_machine.ptr(), "remove_node", name); undo_redo->add_do_method(this, "_update_graph"); @@ -490,7 +490,7 @@ void AnimationNodeStateMachineEditor::_add_animation_type(int p_index) { } updating = true; - undo_redo->create_action("Add Node"); + undo_redo->create_action(TTR("Add Node")); undo_redo->add_do_method(state_machine.ptr(), "add_node", name, anim, add_node_pos); undo_redo->add_undo_method(state_machine.ptr(), "remove_node", name); undo_redo->add_do_method(this, "_update_graph"); @@ -714,12 +714,12 @@ void AnimationNodeStateMachineEditor::_state_machine_draw() { tl.to += offset; } - for (int i = 0; i < node_rects.size(); i++) { - if (node_rects[i].node_name == tl.from_node) { - _clip_src_line_to_rect(tl.from, tl.to, node_rects[i].node); + for (int j = 0; j < node_rects.size(); j++) { + if (node_rects[j].node_name == tl.from_node) { + _clip_src_line_to_rect(tl.from, tl.to, node_rects[j].node); } - if (node_rects[i].node_name == tl.to_node) { - _clip_dst_line_to_rect(tl.from, tl.to, node_rects[i].node); + if (node_rects[j].node_name == tl.to_node) { + _clip_dst_line_to_rect(tl.from, tl.to, node_rects[j].node); } } @@ -1088,7 +1088,7 @@ void AnimationNodeStateMachineEditor::_name_edited(const String &p_text) { } updating = true; - undo_redo->create_action("Node Renamed"); + undo_redo->create_action(TTR("Node Renamed")); undo_redo->add_do_method(state_machine.ptr(), "rename_node", prev_name, name); undo_redo->add_undo_method(state_machine.ptr(), "rename_node", name, prev_name); undo_redo->add_do_method(this, "_update_graph"); @@ -1119,7 +1119,7 @@ void AnimationNodeStateMachineEditor::_erase_selected() { if (selected_node != StringName() && state_machine->has_node(selected_node)) { updating = true; - undo_redo->create_action("Node Removed"); + undo_redo->create_action(TTR("Node Removed")); undo_redo->add_do_method(state_machine.ptr(), "remove_node", selected_node); undo_redo->add_undo_method(state_machine.ptr(), "add_node", selected_node, state_machine->get_node(selected_node), state_machine->get_node_position(selected_node)); for (int i = 0; i < state_machine->get_transition_count(); i++) { @@ -1143,7 +1143,7 @@ void AnimationNodeStateMachineEditor::_erase_selected() { Ref<AnimationNodeStateMachineTransition> tr = state_machine->get_transition(state_machine->find_transition(selected_transition_from, selected_transition_to)); updating = true; - undo_redo->create_action("Transition Removed"); + undo_redo->create_action(TTR("Transition Removed")); undo_redo->add_do_method(state_machine.ptr(), "remove_transition", selected_transition_from, selected_transition_to); undo_redo->add_undo_method(state_machine.ptr(), "add_transition", selected_transition_from, selected_transition_to, tr); undo_redo->add_do_method(this, "_update_graph"); @@ -1169,7 +1169,7 @@ void AnimationNodeStateMachineEditor::_autoplay_selected() { } updating = true; - undo_redo->create_action("Set Start Node (Autoplay)"); + undo_redo->create_action(TTR("Set Start Node (Autoplay)")); undo_redo->add_do_method(state_machine.ptr(), "set_start_node", new_start_node); undo_redo->add_undo_method(state_machine.ptr(), "set_start_node", state_machine->get_start_node()); undo_redo->add_do_method(this, "_update_graph"); @@ -1192,7 +1192,7 @@ void AnimationNodeStateMachineEditor::_end_selected() { } updating = true; - undo_redo->create_action("Set Start Node (Autoplay)"); + undo_redo->create_action(TTR("Set Start Node (Autoplay)")); undo_redo->add_do_method(state_machine.ptr(), "set_end_node", new_end_node); undo_redo->add_undo_method(state_machine.ptr(), "set_end_node", state_machine->get_end_node()); undo_redo->add_do_method(this, "_update_graph"); diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp index c68023ee9b..ab3936407b 100644 --- a/editor/plugins/asset_library_editor_plugin.cpp +++ b/editor/plugins/asset_library_editor_plugin.cpp @@ -1338,6 +1338,7 @@ void EditorAssetLibrary::_bind_methods() { EditorAssetLibrary::EditorAssetLibrary(bool p_templates_only) { + requesting = REQUESTING_NONE; templates_only = p_templates_only; VBoxContainer *library_main = memnew(VBoxContainer); diff --git a/editor/plugins/audio_stream_editor_plugin.h b/editor/plugins/audio_stream_editor_plugin.h index e60bf6a38f..12e4faef94 100644 --- a/editor/plugins/audio_stream_editor_plugin.h +++ b/editor/plugins/audio_stream_editor_plugin.h @@ -33,7 +33,7 @@ #include "editor/editor_node.h" #include "editor/editor_plugin.h" -#include "scene/audio/audio_player.h" +#include "scene/audio/audio_stream_player.h" #include "scene/gui/color_rect.h" #include "scene/resources/texture.h" diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index b2d2704f07..ac05b03ed2 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -42,9 +42,9 @@ #include "scene/2d/light_2d.h" #include "scene/2d/particles_2d.h" #include "scene/2d/polygon_2d.h" -#include "scene/2d/screen_button.h" #include "scene/2d/skeleton_2d.h" #include "scene/2d/sprite.h" +#include "scene/2d/touch_screen_button.h" #include "scene/gui/grid_container.h" #include "scene/gui/nine_patch_rect.h" #include "scene/main/canvas_layer.h" @@ -398,10 +398,10 @@ Rect2 CanvasItemEditor::_get_encompassing_rect_from_list(List<CanvasItem *> p_li // Expand with the other ones for (List<CanvasItem *>::Element *E = p_list.front(); E; E = E->next()) { - CanvasItem *canvas_item = E->get(); - Transform2D xform = canvas_item->get_global_transform_with_canvas(); + CanvasItem *canvas_item2 = E->get(); + Transform2D xform = canvas_item2->get_global_transform_with_canvas(); - Rect2 current_rect = canvas_item->_edit_get_rect(); + Rect2 current_rect = canvas_item2->_edit_get_rect(); rect.expand_to(xform.xform(current_rect.position)); rect.expand_to(xform.xform(current_rect.position + Vector2(current_rect.size.x, 0))); rect.expand_to(xform.xform(current_rect.position + current_rect.size)); @@ -816,10 +816,10 @@ void CanvasItemEditor::_commit_canvas_item_state(List<CanvasItem *> p_canvas_ite undo_redo->add_do_method(canvas_item, "_edit_set_state", canvas_item->_edit_get_state()); undo_redo->add_undo_method(canvas_item, "_edit_set_state", se->undo_state); if (commit_bones) { - for (List<Dictionary>::Element *E = se->pre_drag_bones_undo_state.front(); E; E = E->next()) { + for (List<Dictionary>::Element *F = se->pre_drag_bones_undo_state.front(); F; F = F->next()) { canvas_item = Object::cast_to<CanvasItem>(canvas_item->get_parent()); undo_redo->add_do_method(canvas_item, "_edit_set_state", canvas_item->_edit_get_state()); - undo_redo->add_undo_method(canvas_item, "_edit_set_state", E->get()); + undo_redo->add_undo_method(canvas_item, "_edit_set_state", F->get()); } } } @@ -1921,9 +1921,9 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) { if (drag_selection.size() == 1) { Node2D *node_2d = Object::cast_to<Node2D>(drag_selection[0]); if (node_2d && move_local_base_rotated) { - Transform2D m; - m.rotate(node_2d->get_rotation()); - new_pos += m.xform(drag_to); + Transform2D m2; + m2.rotate(node_2d->get_rotation()); + new_pos += m2.xform(drag_to); } else if (move_local_base) { new_pos += drag_to; } else { @@ -2065,18 +2065,18 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) { // Start dragging if (still_selected) { // Drag the node(s) if requested - List<CanvasItem *> selection = _get_edited_canvas_items(); + List<CanvasItem *> selection2 = _get_edited_canvas_items(); // Remove not movable nodes - for (int i = 0; i < selection.size(); i++) { - if (!_is_node_movable(selection[i], true)) { - selection.erase(selection[i]); + for (int i = 0; i < selection2.size(); i++) { + if (!_is_node_movable(selection2[i], true)) { + selection2.erase(selection2[i]); } } - if (selection.size() > 0) { + if (selection2.size() > 0) { drag_type = DRAG_MOVE; - drag_selection = selection; + drag_selection = selection2; drag_from = click; _save_canvas_item_state(drag_selection); } @@ -3288,7 +3288,7 @@ void CanvasItemEditor::_notification(int p_what) { Control *control = Object::cast_to<Control>(E->get()); if (!control || Object::cast_to<Container>(control->get_parent())) { presets_menu->set_disabled(true); - presets_menu->set_tooltip(TTR("A child of a container gets its anchors and margins values overriden by its parent.")); + presets_menu->set_tooltip(TTR("Children of containers have their anchors and margins values overridden by their parent.")); break; } } @@ -4559,6 +4559,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { snap_grid = true; snap_guides = true; snap_rotation = false; + snap_relative = false; snap_pixel = false; skeleton_show_bones = true; diff --git a/editor/plugins/collision_shape_2d_editor_plugin.cpp b/editor/plugins/collision_shape_2d_editor_plugin.cpp index fc572f54e1..10023d88bf 100644 --- a/editor/plugins/collision_shape_2d_editor_plugin.cpp +++ b/editor/plugins/collision_shape_2d_editor_plugin.cpp @@ -35,9 +35,9 @@ #include "scene/resources/circle_shape_2d.h" #include "scene/resources/concave_polygon_shape_2d.h" #include "scene/resources/convex_polygon_shape_2d.h" +#include "scene/resources/line_shape_2d.h" #include "scene/resources/rectangle_shape_2d.h" #include "scene/resources/segment_shape_2d.h" -#include "scene/resources/shape_line_2d.h" Variant CollisionShape2DEditor::get_handle_value(int idx) const { diff --git a/editor/plugins/editor_preview_plugins.cpp b/editor/plugins/editor_preview_plugins.cpp index 0c0cc9d635..071a0287e6 100644 --- a/editor/plugins/editor_preview_plugins.cpp +++ b/editor/plugins/editor_preview_plugins.cpp @@ -36,7 +36,7 @@ #include "editor/editor_node.h" #include "editor/editor_scale.h" #include "editor/editor_settings.h" -#include "scene/resources/bit_mask.h" +#include "scene/resources/bit_map.h" #include "scene/resources/dynamic_font.h" #include "scene/resources/material.h" #include "scene/resources/mesh.h" diff --git a/editor/plugins/gradient_editor_plugin.cpp b/editor/plugins/gradient_editor_plugin.cpp index 62a9ce719b..e85c475ad7 100644 --- a/editor/plugins/gradient_editor_plugin.cpp +++ b/editor/plugins/gradient_editor_plugin.cpp @@ -51,7 +51,7 @@ void GradientEditor::_ramp_changed() { editing = true; UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo(); - undo_redo->create_action("Gradient Edited"); + undo_redo->create_action(TTR("Gradient Edited")); undo_redo->add_do_method(gradient.ptr(), "set_offsets", get_offsets()); undo_redo->add_do_method(gradient.ptr(), "set_colors", get_colors()); undo_redo->add_undo_method(gradient.ptr(), "set_offsets", gradient->get_offsets()); diff --git a/editor/plugins/item_list_editor_plugin.cpp b/editor/plugins/item_list_editor_plugin.cpp index db0816064c..b3f3ccf501 100644 --- a/editor/plugins/item_list_editor_plugin.cpp +++ b/editor/plugins/item_list_editor_plugin.cpp @@ -353,6 +353,7 @@ void ItemListEditor::_bind_methods() { ItemListEditor::ItemListEditor() { selected_idx = -1; + item_list = NULL; toolbar_button = memnew(ToolButton); toolbar_button->set_text(TTR("Items")); diff --git a/editor/plugins/mesh_instance_editor_plugin.cpp b/editor/plugins/mesh_instance_editor_plugin.cpp index 40ec03bc96..3e10cdbbfa 100644 --- a/editor/plugins/mesh_instance_editor_plugin.cpp +++ b/editor/plugins/mesh_instance_editor_plugin.cpp @@ -198,14 +198,14 @@ void MeshInstanceEditor::_menu_option(int p_option) { } break; case MENU_OPTION_CREATE_UV2: { - Ref<ArrayMesh> mesh = node->get_mesh(); - if (!mesh.is_valid()) { + Ref<ArrayMesh> mesh2 = node->get_mesh(); + if (!mesh2.is_valid()) { err_dialog->set_text(TTR("Contained Mesh is not of type ArrayMesh.")); err_dialog->popup_centered_minsize(); return; } - Error err = mesh->lightmap_unwrap(node->get_global_transform()); + Error err = mesh2->lightmap_unwrap(node->get_global_transform()); if (err != OK) { err_dialog->set_text(TTR("UV Unwrap failed, mesh may not be manifold?")); err_dialog->popup_centered_minsize(); @@ -214,8 +214,8 @@ void MeshInstanceEditor::_menu_option(int p_option) { } break; case MENU_OPTION_DEBUG_UV1: { - Ref<Mesh> mesh = node->get_mesh(); - if (!mesh.is_valid()) { + Ref<Mesh> mesh2 = node->get_mesh(); + if (!mesh2.is_valid()) { err_dialog->set_text(TTR("No mesh to debug.")); err_dialog->popup_centered_minsize(); return; @@ -223,8 +223,8 @@ void MeshInstanceEditor::_menu_option(int p_option) { _create_uv_lines(0); } break; case MENU_OPTION_DEBUG_UV2: { - Ref<Mesh> mesh = node->get_mesh(); - if (!mesh.is_valid()) { + Ref<Mesh> mesh2 = node->get_mesh(); + if (!mesh2.is_valid()) { err_dialog->set_text(TTR("No mesh to debug.")); err_dialog->popup_centered_minsize(); return; diff --git a/editor/plugins/particles_2d_editor_plugin.cpp b/editor/plugins/particles_2d_editor_plugin.cpp index a944674cbd..bb7d50a9c1 100644 --- a/editor/plugins/particles_2d_editor_plugin.cpp +++ b/editor/plugins/particles_2d_editor_plugin.cpp @@ -91,6 +91,7 @@ void Particles2DEditorPlugin::_menu_callback(int p_idx) { cpu_particles->set_transform(particles->get_transform()); cpu_particles->set_visible(particles->is_visible()); cpu_particles->set_pause_mode(particles->get_pause_mode()); + cpu_particles->set_z_index(particles->get_z_index()); EditorNode::get_singleton()->get_scene_tree_dock()->replace_node(particles, cpu_particles, false); diff --git a/editor/plugins/path_2d_editor_plugin.cpp b/editor/plugins/path_2d_editor_plugin.cpp index 354475d268..a10eddb131 100644 --- a/editor/plugins/path_2d_editor_plugin.cpp +++ b/editor/plugins/path_2d_editor_plugin.cpp @@ -180,11 +180,11 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { // Check for segment split. if (mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT && mode == MODE_EDIT && on_edge == true) { - Vector2 gpoint = mb->get_position(); + Vector2 gpoint2 = mb->get_position(); Ref<Curve2D> curve = node->get_curve(); int insertion_point = -1; - float mbLength = curve->get_closest_offset(xform.affine_inverse().xform(gpoint)); + float mbLength = curve->get_closest_offset(xform.affine_inverse().xform(gpoint2)); int len = curve->get_point_count(); for (int i = 0; i < len - 1; i++) { float compareLength = curve->get_closest_offset(curve->get_point_position(i + 1)); @@ -195,7 +195,7 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { insertion_point = curve->get_point_count() - 2; undo_redo->create_action(TTR("Split Curve")); - undo_redo->add_do_method(curve.ptr(), "add_point", xform.affine_inverse().xform(gpoint), Vector2(0, 0), Vector2(0, 0), insertion_point + 1); + undo_redo->add_do_method(curve.ptr(), "add_point", xform.affine_inverse().xform(gpoint2), Vector2(0, 0), Vector2(0, 0), insertion_point + 1); undo_redo->add_undo_method(curve.ptr(), "remove_point", insertion_point + 1); undo_redo->add_do_method(canvas_item_editor, "update_viewport"); undo_redo->add_undo_method(canvas_item_editor, "update_viewport"); @@ -204,7 +204,7 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { action = ACTION_MOVING_POINT; action_point = insertion_point + 1; moving_from = curve->get_point_position(action_point); - moving_screen_from = gpoint; + moving_screen_from = gpoint2; canvas_item_editor->update_viewport(); diff --git a/editor/plugins/polygon_2d_editor_plugin.cpp b/editor/plugins/polygon_2d_editor_plugin.cpp index 1d7b4ffa41..0dbbaf4177 100644 --- a/editor/plugins/polygon_2d_editor_plugin.cpp +++ b/editor/plugins/polygon_2d_editor_plugin.cpp @@ -45,6 +45,7 @@ Node2D *Polygon2DEditor::_get_node() const { void Polygon2DEditor::_set_node(Node *p_polygon) { node = Object::cast_to<Polygon2D>(p_polygon); + _update_polygon_editing_state(); } Vector2 Polygon2DEditor::_get_offset(int p_idx) const { @@ -53,6 +54,7 @@ Vector2 Polygon2DEditor::_get_offset(int p_idx) const { } int Polygon2DEditor::_get_polygon_count() const { + if (node->get_internal_vertex_count() > 0) { return 0; //do not edit if internal vertices exist } else { @@ -365,6 +367,8 @@ void Polygon2DEditor::_cancel_editing() { node->set_vertex_colors(uv_create_colors_prev); node->call("_set_bones", uv_create_bones_prev); node->set_polygons(polygons_prev); + + _update_polygon_editing_state(); } else if (uv_drag) { uv_drag = false; if (uv_edit_mode[0]->is_pressed()) { // Edit UV. @@ -377,9 +381,20 @@ void Polygon2DEditor::_cancel_editing() { polygon_create.clear(); } +void Polygon2DEditor::_update_polygon_editing_state() { + + if (!_get_node()) + return; + + if (node->get_internal_vertex_count() > 0) + disable_polygon_editing(true, TTR("Polygon 2D has internal vertices, so it can no longer be edited in the viewport.")); + else + disable_polygon_editing(false, String()); +} + void Polygon2DEditor::_commit_action() { - // Makes that undo/redoing actions made outside of the UV editor still affects its polygon. + // Makes that undo/redoing actions made outside of the UV editor still affect its polygon. undo_redo->add_do_method(uv_edit_draw, "update"); undo_redo->add_undo_method(uv_edit_draw, "update"); undo_redo->add_do_method(CanvasItemEditor::get_singleton(), "update_viewport"); @@ -480,6 +495,7 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { uv_create_colors_prev = node->get_vertex_colors(); uv_create_bones_prev = node->call("_get_bones"); polygons_prev = node->get_polygons(); + disable_polygon_editing(false, String()); node->set_polygon(points_prev); node->set_uv(points_prev); node->set_internal_vertex_count(0); @@ -501,6 +517,8 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { undo_redo->add_undo_method(node, "set_vertex_colors", uv_create_colors_prev); undo_redo->add_do_method(node, "clear_bones"); undo_redo->add_undo_method(node, "_set_bones", uv_create_bones_prev); + undo_redo->add_do_method(this, "_update_polygon_editing_state"); + undo_redo->add_undo_method(this, "_update_polygon_editing_state"); undo_redo->add_do_method(uv_edit_draw, "update"); undo_redo->add_undo_method(uv_edit_draw, "update"); undo_redo->commit_action(); @@ -552,7 +570,8 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { } undo_redo->add_do_method(node, "set_internal_vertex_count", internal_vertices + 1); undo_redo->add_undo_method(node, "set_internal_vertex_count", internal_vertices); - + undo_redo->add_do_method(this, "_update_polygon_editing_state"); + undo_redo->add_undo_method(this, "_update_polygon_editing_state"); undo_redo->add_do_method(uv_edit_draw, "update"); undo_redo->add_undo_method(uv_edit_draw, "update"); undo_redo->commit_action(); @@ -606,7 +625,8 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { } undo_redo->add_do_method(node, "set_internal_vertex_count", internal_vertices - 1); undo_redo->add_undo_method(node, "set_internal_vertex_count", internal_vertices); - + undo_redo->add_do_method(this, "_update_polygon_editing_state"); + undo_redo->add_undo_method(this, "_update_polygon_editing_state"); undo_redo->add_do_method(uv_edit_draw, "update"); undo_redo->add_undo_method(uv_edit_draw, "update"); undo_redo->commit_action(); @@ -1028,6 +1048,9 @@ void Polygon2DEditor::_uv_draw() { Ref<Texture> internal_handle = get_icon("EditorInternalHandle", "EditorIcons"); Color poly_line_color = Color(0.9, 0.5, 0.5); + if (polygons.size() || polygon_create.size()) { + poly_line_color.a *= 0.25; + } Color polygon_line_color = Color(0.5, 0.5, 0.9); Vector<Color> polygon_fill_color; { @@ -1041,14 +1064,38 @@ void Polygon2DEditor::_uv_draw() { int uv_draw_max = uvs.size(); + uv_draw_max -= node->get_internal_vertex_count(); + if (uv_draw_max < 0) { + uv_draw_max = 0; + } + + for (int i = 0; i < uvs.size(); i++) { + + int next = uv_draw_max > 0 ? (i + 1) % uv_draw_max : 0; + + if (i < uv_draw_max && uv_drag && uv_move_current == UV_MODE_EDIT_POINT && EDITOR_DEF("editors/poly_editor/show_previous_outline", true)) { + uv_edit_draw->draw_line(mtx.xform(points_prev[i]), mtx.xform(points_prev[next]), prev_color, 2 * EDSCALE); + } + + Vector2 next_point = uvs[next]; + if (uv_create && i == uvs.size() - 1) { + next_point = uv_create_to; + } + if (i < uv_draw_max /*&& polygons.size() == 0 && polygon_create.size() == 0*/) { //if using or creating polygons, do not show outline (will show polygons instead) + uv_edit_draw->draw_line(mtx.xform(uvs[i]), mtx.xform(next_point), poly_line_color, 2 * EDSCALE); + } + + rect.expand_to(mtx.basis_xform(uvs[i])); + } + for (int i = 0; i < polygons.size(); i++) { PoolVector<int> points = polygons[i]; Vector<Vector2> polypoints; - for (int i = 0; i < points.size(); i++) { - int next = (i + 1) % points.size(); + for (int j = 0; j < points.size(); j++) { + int next = (j + 1) % points.size(); - int idx = points[i]; + int idx = points[j]; int idx_next = points[next]; if (idx < 0 || idx >= uvs.size()) continue; @@ -1063,27 +1110,8 @@ void Polygon2DEditor::_uv_draw() { } } - uv_draw_max -= node->get_internal_vertex_count(); - if (uv_draw_max < 0) { - uv_draw_max = 0; - } - for (int i = 0; i < uvs.size(); i++) { - int next = uv_draw_max > 0 ? (i + 1) % uv_draw_max : 0; - - if (i < uv_draw_max && uv_drag && uv_move_current == UV_MODE_EDIT_POINT && EDITOR_DEF("editors/poly_editor/show_previous_outline", true)) { - uv_edit_draw->draw_line(mtx.xform(points_prev[i]), mtx.xform(points_prev[next]), prev_color, 2 * EDSCALE); - } - - Vector2 next_point = uvs[next]; - if (uv_create && i == uvs.size() - 1) { - next_point = uv_create_to; - } - if (i < uv_draw_max && polygons.size() == 0 && polygon_create.size() == 0) { //if using or creating polygons, do not show outline (will show polygons instead) - uv_edit_draw->draw_line(mtx.xform(uvs[i]), mtx.xform(next_point), poly_line_color, 2 * EDSCALE); - } - if (weight_r.ptr()) { Vector2 draw_pos = mtx.xform(uvs[i]); float weight = weight_r[i]; @@ -1095,14 +1123,13 @@ void Polygon2DEditor::_uv_draw() { uv_edit_draw->draw_texture(internal_handle, mtx.xform(uvs[i]) - internal_handle->get_size() * 0.5); } } - rect.expand_to(mtx.basis_xform(uvs[i])); } if (polygon_create.size()) { for (int i = 0; i < polygon_create.size(); i++) { Vector2 from = uvs[polygon_create[i]]; Vector2 to = (i + 1) < polygon_create.size() ? uvs[polygon_create[i + 1]] : uv_create_to; - uv_edit_draw->draw_line(mtx.xform(from), mtx.xform(to), poly_line_color, 2); + uv_edit_draw->draw_line(mtx.xform(from), mtx.xform(to), polygon_line_color, 2); } } @@ -1216,6 +1243,7 @@ void Polygon2DEditor::_bind_methods() { ClassDB::bind_method(D_METHOD("_uv_edit_popup_hide"), &Polygon2DEditor::_uv_edit_popup_hide); ClassDB::bind_method(D_METHOD("_sync_bones"), &Polygon2DEditor::_sync_bones); ClassDB::bind_method(D_METHOD("_update_bone_list"), &Polygon2DEditor::_update_bone_list); + ClassDB::bind_method(D_METHOD("_update_polygon_editing_state"), &Polygon2DEditor::_update_polygon_editing_state); ClassDB::bind_method(D_METHOD("_bone_paint_selected"), &Polygon2DEditor::_bone_paint_selected); } diff --git a/editor/plugins/polygon_2d_editor_plugin.h b/editor/plugins/polygon_2d_editor_plugin.h index d1849dd09b..24ca2ea3f4 100644 --- a/editor/plugins/polygon_2d_editor_plugin.h +++ b/editor/plugins/polygon_2d_editor_plugin.h @@ -128,6 +128,7 @@ class Polygon2DEditor : public AbstractPolygon2DEditor { virtual void _menu_option(int p_option); void _cancel_editing(); + void _update_polygon_editing_state(); void _uv_scroll_changed(float); void _uv_input(const Ref<InputEvent> &p_input); diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp index 60dc156782..e95b1356bf 100644 --- a/editor/plugins/script_text_editor.cpp +++ b/editor/plugins/script_text_editor.cpp @@ -273,18 +273,12 @@ void ScriptTextEditor::_set_theme_for_script() { } } -void ScriptTextEditor::_toggle_warning_pannel(const Ref<InputEvent> &p_event) { - Ref<InputEventMouseButton> mb = p_event; - if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { - warnings_panel->set_visible(!warnings_panel->is_visible()); - } +void ScriptTextEditor::_show_warnings_panel(bool p_show) { + warnings_panel->set_visible(p_show); } -void ScriptTextEditor::_error_pressed(const Ref<InputEvent> &p_event) { - Ref<InputEventMouseButton> mb = p_event; - if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { - code_editor->goto_error(); - } +void ScriptTextEditor::_error_pressed() { + code_editor->goto_error(); } void ScriptTextEditor::_warning_clicked(Variant p_line) { @@ -468,7 +462,7 @@ void ScriptTextEditor::_validate_script() { } } - code_editor->get_warning_count_label()->set_text(itos(warnings.size())); + code_editor->set_warning_nb(warnings.size()); warnings_panel->clear(); warnings_panel->push_table(3); for (List<ScriptLanguage::Warning>::Element *E = warnings.front(); E; E = E->next()) { @@ -1107,7 +1101,7 @@ void ScriptTextEditor::_bind_methods() { ClassDB::bind_method("_goto_line", &ScriptTextEditor::_goto_line); ClassDB::bind_method("_lookup_symbol", &ScriptTextEditor::_lookup_symbol); ClassDB::bind_method("_text_edit_gui_input", &ScriptTextEditor::_text_edit_gui_input); - ClassDB::bind_method("_toggle_warning_pannel", &ScriptTextEditor::_toggle_warning_pannel); + ClassDB::bind_method("_show_warnings_panel", &ScriptTextEditor::_show_warnings_panel); ClassDB::bind_method("_error_pressed", &ScriptTextEditor::_error_pressed); ClassDB::bind_method("_warning_clicked", &ScriptTextEditor::_warning_clicked); ClassDB::bind_method("_color_changed", &ScriptTextEditor::_color_changed); @@ -1427,7 +1421,7 @@ ScriptTextEditor::ScriptTextEditor() { code_editor = memnew(CodeTextEditor); editor_box->add_child(code_editor); - code_editor->add_constant_override("separation", 0); + code_editor->add_constant_override("separation", 2); code_editor->set_anchors_and_margins_preset(Control::PRESET_WIDE); code_editor->connect("validate_script", this, "_validate_script"); code_editor->connect("load_theme_settings", this, "_load_theme_settings"); @@ -1445,9 +1439,8 @@ ScriptTextEditor::ScriptTextEditor() { warnings_panel->set_focus_mode(FOCUS_CLICK); warnings_panel->hide(); - code_editor->get_error_label()->connect("gui_input", this, "_error_pressed"); - code_editor->get_warning_label()->connect("gui_input", this, "_toggle_warning_pannel"); - code_editor->get_warning_count_label()->connect("gui_input", this, "_toggle_warning_pannel"); + code_editor->connect("error_pressed", this, "_error_pressed"); + code_editor->connect("show_warnings_panel", this, "_show_warnings_panel"); warnings_panel->connect("meta_clicked", this, "_warning_clicked"); update_settings(); diff --git a/editor/plugins/script_text_editor.h b/editor/plugins/script_text_editor.h index 856e442d82..f83aadddef 100644 --- a/editor/plugins/script_text_editor.h +++ b/editor/plugins/script_text_editor.h @@ -125,8 +125,8 @@ protected: void _code_complete_script(const String &p_code, List<String> *r_options, bool &r_force); void _load_theme_settings(); void _set_theme_for_script(); - void _toggle_warning_pannel(const Ref<InputEvent> &p_event); - void _error_pressed(const Ref<InputEvent> &p_event); + void _show_warnings_panel(bool p_show); + void _error_pressed(); void _warning_clicked(Variant p_line); void _notification(int p_what); diff --git a/editor/plugins/skeleton_2d_editor_plugin.cpp b/editor/plugins/skeleton_2d_editor_plugin.cpp index 619d54b202..ef3e17279c 100644 --- a/editor/plugins/skeleton_2d_editor_plugin.cpp +++ b/editor/plugins/skeleton_2d_editor_plugin.cpp @@ -63,7 +63,7 @@ void Skeleton2DEditor::_menu_option(int p_option) { return; } UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); - ur->create_action("Create Rest Pose from Bones"); + ur->create_action(TTR("Create Rest Pose from Bones")); for (int i = 0; i < node->get_bone_count(); i++) { Bone2D *bone = node->get_bone(i); ur->add_do_method(bone, "set_rest", bone->get_transform()); @@ -79,7 +79,7 @@ void Skeleton2DEditor::_menu_option(int p_option) { return; } UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); - ur->create_action("Set Rest Pose to Bones"); + ur->create_action(TTR("Set Rest Pose to Bones")); for (int i = 0; i < node->get_bone_count(); i++) { Bone2D *bone = node->get_bone(i); ur->add_do_method(bone, "set_transform", bone->get_rest()); diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp index 9ece812c49..1e9ff87fd3 100644 --- a/editor/plugins/spatial_editor_plugin.cpp +++ b/editor/plugins/spatial_editor_plugin.cpp @@ -35,7 +35,7 @@ #include "core/os/keyboard.h" #include "core/print_string.h" #include "core/project_settings.h" -#include "core/sort.h" +#include "core/sort_array.h" #include "editor/editor_node.h" #include "editor/editor_settings.h" #include "editor/plugins/animation_player_editor_plugin.h" @@ -2262,7 +2262,7 @@ void SpatialEditorViewport::_notification(int p_what) { if (show_fps) { String text; const float temp_fps = Engine::get_singleton()->get_frames_per_second(); - text += TTR("FPS") + ": " + itos(temp_fps) + " (" + String::num(1000.0f / temp_fps, 2) + " ms)"; + text += TTR(vformat("FPS: %d (%s ms)", temp_fps, String::num(1000.0f / temp_fps, 2))); fps_label->set_text(text); } @@ -2546,7 +2546,7 @@ void SpatialEditorViewport::_menu_option(int p_option) { List<Node *> &selection = editor_selection->get_selected_node_list(); - undo_redo->create_action(TTR("Align with view")); + undo_redo->create_action(TTR("Align with View")); for (List<Node *>::Element *E = selection.front(); E; E = E->next()) { Spatial *sp = Object::cast_to<Spatial>(E->get()); @@ -3554,6 +3554,8 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed fps_label->set_anchor_and_margin(MARGIN_TOP, ANCHOR_BEGIN, 10 * EDSCALE); fps_label->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, -10 * EDSCALE); fps_label->set_h_grow_direction(GROW_DIRECTION_BEGIN); + fps_label->set_tooltip(TTR("Note: The FPS value displayed is the editor's framerate.\nIt cannot be used as a reliable indication of in-game performance.")); + fps_label->set_mouse_filter(MOUSE_FILTER_PASS); // Otherwise tooltip doesn't show. surface->add_child(fps_label); fps_label->hide(); @@ -4693,10 +4695,10 @@ void SpatialEditor::_init_indicators() { plane_mat->set_on_top_of_alpha(); plane_mat->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); plane_mat->set_cull_mode(SpatialMaterial::CULL_DISABLED); - Color col; - col[i] = 1.0; - col.a = gizmo_alph; - plane_mat->set_albedo(col); + Color col2; + col2[i] = 1.0; + col2.a = gizmo_alph; + plane_mat->set_albedo(col2); plane_gizmo_color[i] = plane_mat; // needed, so we can draw planes from both sides surftool->set_material(plane_mat); surftool->commit(move_plane_gizmo[i]); @@ -4822,10 +4824,10 @@ void SpatialEditor::_init_indicators() { plane_mat->set_on_top_of_alpha(); plane_mat->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); plane_mat->set_cull_mode(SpatialMaterial::CULL_DISABLED); - Color col; - col[i] = 1.0; - col.a = gizmo_alph; - plane_mat->set_albedo(col); + Color col2; + col2[i] = 1.0; + col2.a = gizmo_alph; + plane_mat->set_albedo(col2); plane_gizmo_color[i] = plane_mat; // needed, so we can draw planes from both sides surftool->set_material(plane_mat); surftool->commit(scale_plane_gizmo[i]); @@ -4856,6 +4858,13 @@ void SpatialEditor::_update_gizmos_menu() { } } +void SpatialEditor::_update_gizmos_menu_theme() { + for (int i = 0; i < gizmo_plugins.size(); ++i) { + if (!gizmo_plugins[i]->can_be_hidden()) continue; + gizmos_menu->set_item_icon(gizmos_menu->get_item_index(i), gizmos_menu->get_icon("visibility_visible")); + } +} + void SpatialEditor::_init_grid() { PoolVector<Color> grid_colors[3]; @@ -5046,7 +5055,7 @@ void SpatialEditor::snap_selected_nodes_to_floor() { Array keys = snap_data.keys(); if (keys.size()) { - undo_redo->create_action("Snap Nodes To Floor"); + undo_redo->create_action(TTR("Snap Nodes To Floor")); for (int i = 0; i < keys.size(); i++) { Node *node = keys[i]; @@ -5145,20 +5154,17 @@ void SpatialEditor::_notification(int p_what) { get_tree()->connect("node_removed", this, "_node_removed"); EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor()->connect("node_changed", this, "_refresh_menu_icons"); editor_selection->connect("selection_changed", this, "_refresh_menu_icons"); - } - - if (p_what == NOTIFICATION_ENTER_TREE) { + } else if (p_what == NOTIFICATION_ENTER_TREE) { _register_all_gizmos(); _update_gizmos_menu(); _init_indicators(); - } - - if (p_what == NOTIFICATION_EXIT_TREE) { + } else if (p_what == NOTIFICATION_THEME_CHANGED) { + _update_gizmos_menu_theme(); + } else if (p_what == NOTIFICATION_EXIT_TREE) { _finish_indicators(); - } - if (p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) { + } else if (p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) { tool_button[SpatialEditor::TOOL_MODE_SELECT]->set_icon(get_icon("ToolSelect", "EditorIcons")); tool_button[SpatialEditor::TOOL_MODE_MOVE]->set_icon(get_icon("ToolMove", "EditorIcons")); tool_button[SpatialEditor::TOOL_MODE_ROTATE]->set_icon(get_icon("ToolRotate", "EditorIcons")); diff --git a/editor/plugins/spatial_editor_plugin.h b/editor/plugins/spatial_editor_plugin.h index 2dc627cb27..364b0085f7 100644 --- a/editor/plugins/spatial_editor_plugin.h +++ b/editor/plugins/spatial_editor_plugin.h @@ -618,6 +618,7 @@ private: void _instance_scene(); void _init_indicators(); void _update_gizmos_menu(); + void _update_gizmos_menu_theme(); void _init_grid(); void _finish_indicators(); void _finish_grid(); diff --git a/editor/plugins/sprite_frames_editor_plugin.cpp b/editor/plugins/sprite_frames_editor_plugin.cpp index b712cfc9d3..89bb7440fe 100644 --- a/editor/plugins/sprite_frames_editor_plugin.cpp +++ b/editor/plugins/sprite_frames_editor_plugin.cpp @@ -40,10 +40,8 @@ void SpriteFramesEditor::_gui_input(Ref<InputEvent> p_event) { void SpriteFramesEditor::_notification(int p_what) { - if (p_what == NOTIFICATION_PHYSICS_PROCESS) { - } - if (p_what == NOTIFICATION_ENTER_TREE) { + load->set_icon(get_icon("Load", "EditorIcons")); copy->set_icon(get_icon("ActionCopy", "EditorIcons")); paste->set_icon(get_icon("ActionPaste", "EditorIcons")); @@ -54,14 +52,9 @@ void SpriteFramesEditor::_notification(int p_what) { _delete->set_icon(get_icon("Remove", "EditorIcons")); new_anim->set_icon(get_icon("New", "EditorIcons")); remove_anim->set_icon(get_icon("Remove", "EditorIcons")); - } - - if (p_what == NOTIFICATION_READY) { + } else if (p_what == NOTIFICATION_READY) { - //NodePath("/root")->connect("node_removed", this,"_node_removed",Vector<Variant>(),true); - } - - if (p_what == NOTIFICATION_DRAW) { + add_constant_override("autohide", 1); // Fixes the dragger always showing up. } } @@ -649,7 +642,6 @@ void SpriteFramesEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da void SpriteFramesEditor::_bind_methods() { - ClassDB::bind_method(D_METHOD("_gui_input"), &SpriteFramesEditor::_gui_input); ClassDB::bind_method(D_METHOD("_load_pressed"), &SpriteFramesEditor::_load_pressed); ClassDB::bind_method(D_METHOD("_empty_pressed"), &SpriteFramesEditor::_empty_pressed); ClassDB::bind_method(D_METHOD("_empty2_pressed"), &SpriteFramesEditor::_empty2_pressed); @@ -673,31 +665,25 @@ void SpriteFramesEditor::_bind_methods() { SpriteFramesEditor::SpriteFramesEditor() { - //add_style_override("panel", EditorNode::get_singleton()->get_gui_base()->get_stylebox("panel","Panel")); - - split = memnew(HSplitContainer); - add_child(split); - VBoxContainer *vbc_animlist = memnew(VBoxContainer); - split->add_child(vbc_animlist); + add_child(vbc_animlist); vbc_animlist->set_custom_minimum_size(Size2(150, 0) * EDSCALE); - //vbc_animlist->set_v_size_flags(SIZE_EXPAND_FILL); VBoxContainer *sub_vb = memnew(VBoxContainer); - vbc_animlist->add_margin_child(TTR("Animations"), sub_vb, true); + vbc_animlist->add_margin_child(TTR("Animations:"), sub_vb, true); sub_vb->set_v_size_flags(SIZE_EXPAND_FILL); HBoxContainer *hbc_animlist = memnew(HBoxContainer); sub_vb->add_child(hbc_animlist); - new_anim = memnew(Button); - new_anim->set_flat(true); + new_anim = memnew(ToolButton); + new_anim->set_tooltip(TTR("New Animation")); hbc_animlist->add_child(new_anim); new_anim->set_h_size_flags(SIZE_EXPAND_FILL); new_anim->connect("pressed", this, "_animation_add"); - remove_anim = memnew(Button); - remove_anim->set_flat(true); + remove_anim = memnew(ToolButton); + remove_anim->set_tooltip(TTR("Remove Animation")); hbc_animlist->add_child(remove_anim); remove_anim->connect("pressed", this, "_animation_remove"); @@ -722,56 +708,47 @@ SpriteFramesEditor::SpriteFramesEditor() { anim_loop->connect("pressed", this, "_animation_loop_changed"); VBoxContainer *vbc = memnew(VBoxContainer); - split->add_child(vbc); + add_child(vbc); vbc->set_h_size_flags(SIZE_EXPAND_FILL); sub_vb = memnew(VBoxContainer); - vbc->add_margin_child(TTR("Animation Frames"), sub_vb, true); + vbc->add_margin_child(TTR("Animation Frames:"), sub_vb, true); HBoxContainer *hbc = memnew(HBoxContainer); sub_vb->add_child(hbc); - //animations = memnew( ItemList ); - - load = memnew(Button); - load->set_flat(true); + load = memnew(ToolButton); load->set_tooltip(TTR("Load Resource")); hbc->add_child(load); - copy = memnew(Button); - copy->set_flat(true); + copy = memnew(ToolButton); copy->set_tooltip(TTR("Copy")); hbc->add_child(copy); - paste = memnew(Button); - paste->set_flat(true); + paste = memnew(ToolButton); paste->set_tooltip(TTR("Paste")); hbc->add_child(paste); - empty = memnew(Button); - empty->set_flat(true); + empty = memnew(ToolButton); empty->set_tooltip(TTR("Insert Empty (Before)")); hbc->add_child(empty); - empty2 = memnew(Button); - empty2->set_flat(true); + empty2 = memnew(ToolButton); empty2->set_tooltip(TTR("Insert Empty (After)")); hbc->add_child(empty2); hbc->add_spacer(false); - move_up = memnew(Button); - move_up->set_flat(true); + move_up = memnew(ToolButton); move_up->set_tooltip(TTR("Move (Before)")); hbc->add_child(move_up); - move_down = memnew(Button); - move_down->set_flat(true); + move_down = memnew(ToolButton); move_down->set_tooltip(TTR("Move (After)")); hbc->add_child(move_down); - _delete = memnew(Button); - _delete->set_flat(true); + _delete = memnew(ToolButton); + _delete->set_tooltip(TTR("Delete")); hbc->add_child(_delete); file = memnew(EditorFileDialog); @@ -787,7 +764,6 @@ SpriteFramesEditor::SpriteFramesEditor() { tree->set_fixed_column_width(thumbnail_size * 3 / 2); tree->set_max_text_lines(2); tree->set_fixed_icon_size(Size2(thumbnail_size, thumbnail_size)); - //tree->set_min_icon_size(Size2(thumbnail_size,thumbnail_size)); tree->set_drag_forwarding(this); sub_vb->add_child(tree); diff --git a/editor/plugins/sprite_frames_editor_plugin.h b/editor/plugins/sprite_frames_editor_plugin.h index 3ef4ba290b..55dd10074e 100644 --- a/editor/plugins/sprite_frames_editor_plugin.h +++ b/editor/plugins/sprite_frames_editor_plugin.h @@ -39,25 +39,25 @@ #include "scene/gui/split_container.h" #include "scene/gui/tree.h" -class SpriteFramesEditor : public PanelContainer { - - GDCLASS(SpriteFramesEditor, PanelContainer); - - Button *load; - Button *_delete; - Button *copy; - Button *paste; - Button *empty; - Button *empty2; - Button *move_up; - Button *move_down; +class SpriteFramesEditor : public HSplitContainer { + + GDCLASS(SpriteFramesEditor, HSplitContainer); + + ToolButton *load; + ToolButton *_delete; + ToolButton *copy; + ToolButton *paste; + ToolButton *empty; + ToolButton *empty2; + ToolButton *move_up; + ToolButton *move_down; ItemList *tree; bool loading_scene; int sel; HSplitContainer *split; - Button *new_anim; - Button *remove_anim; + ToolButton *new_anim; + ToolButton *remove_anim; Tree *animations; SpinBox *anim_speed; diff --git a/editor/plugins/tile_map_editor_plugin.cpp b/editor/plugins/tile_map_editor_plugin.cpp index a967374eb9..1a367b61dd 100644 --- a/editor/plugins/tile_map_editor_plugin.cpp +++ b/editor/plugins/tile_map_editor_plugin.cpp @@ -477,17 +477,17 @@ void TileMapEditor::_update_palette() { if (sel_tile != TileMap::INVALID_CELL) { if ((manual_autotile && tileset->tile_get_tile_mode(sel_tile) == TileSet::AUTO_TILE) || tileset->tile_get_tile_mode(sel_tile) == TileSet::ATLAS_TILE) { - const Map<Vector2, uint16_t> &tiles = tileset->autotile_get_bitmask_map(sel_tile); + const Map<Vector2, uint16_t> &tiles2 = tileset->autotile_get_bitmask_map(sel_tile); - Vector<Vector2> entries; - for (const Map<Vector2, uint16_t>::Element *E = tiles.front(); E; E = E->next()) { - entries.push_back(E->key()); + Vector<Vector2> entries2; + for (const Map<Vector2, uint16_t>::Element *E = tiles2.front(); E; E = E->next()) { + entries2.push_back(E->key()); } - entries.sort(); + entries2.sort(); Ref<Texture> tex = tileset->tile_get_texture(sel_tile); - for (int i = 0; i < entries.size(); i++) { + for (int i = 0; i < entries2.size(); i++) { manual_palette->add_item(String()); @@ -496,7 +496,7 @@ void TileMapEditor::_update_palette() { Rect2 region = tileset->tile_get_region(sel_tile); int spacing = tileset->autotile_get_spacing(sel_tile); region.size = tileset->autotile_get_size(sel_tile); // !! - region.position += (region.size + Vector2(spacing, spacing)) * entries[i]; + region.position += (region.size + Vector2(spacing, spacing)) * entries2[i]; if (!region.has_no_area()) manual_palette->set_item_icon_region(manual_palette->get_item_count() - 1, region); @@ -504,16 +504,16 @@ void TileMapEditor::_update_palette() { manual_palette->set_item_icon(manual_palette->get_item_count() - 1, tex); } - manual_palette->set_item_metadata(manual_palette->get_item_count() - 1, entries[i]); + manual_palette->set_item_metadata(manual_palette->get_item_count() - 1, entries2[i]); } } } if (manual_palette->get_item_count() > 0) { // Only show the manual palette if at least tile exists in it - int selected = manual_palette->get_current(); - if (selected == -1) selected = 0; - manual_palette->set_current(selected); + int selected2 = manual_palette->get_current(); + if (selected2 == -1) selected2 = 0; + manual_palette->set_current(selected2); manual_palette->show(); } @@ -1157,7 +1157,7 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) { if (points.size() == 0) return false; - undo_redo->create_action("Bucket Fill"); + undo_redo->create_action(TTR("Bucket Fill")); undo_redo->add_do_method(this, "_erase_points", points); undo_redo->add_undo_method(this, "_fill_points", points, pop); diff --git a/editor/plugins/tile_set_editor_plugin.cpp b/editor/plugins/tile_set_editor_plugin.cpp index 1a687a4009..26f8b74862 100644 --- a/editor/plugins/tile_set_editor_plugin.cpp +++ b/editor/plugins/tile_set_editor_plugin.cpp @@ -232,6 +232,7 @@ void TileSetEditor::_notification(int p_what) { tools[BITMASK_PASTE]->set_icon(get_icon("Override", "EditorIcons")); tools[BITMASK_CLEAR]->set_icon(get_icon("Clear", "EditorIcons")); tools[SHAPE_NEW_POLYGON]->set_icon(get_icon("CollisionPolygon2D", "EditorIcons")); + tools[SHAPE_NEW_RECTANGLE]->set_icon(get_icon("CollisionShape2D", "EditorIcons")); tools[SHAPE_DELETE]->set_icon(get_icon("Remove", "EditorIcons")); tools[SHAPE_KEEP_INSIDE_TILE]->set_icon(get_icon("Snap", "EditorIcons")); tools[TOOL_GRID_SNAP]->set_icon(get_icon("SnapGrid", "EditorIcons")); @@ -377,6 +378,12 @@ TileSetEditor::TileSetEditor(EditorNode *p_editor) { tools[BITMASK_CLEAR]->connect("pressed", this, "_on_tool_clicked", varray(BITMASK_CLEAR)); toolbar->add_child(tools[BITMASK_CLEAR]); + tools[SHAPE_NEW_RECTANGLE] = memnew(ToolButton); + toolbar->add_child(tools[SHAPE_NEW_RECTANGLE]); + tools[SHAPE_NEW_RECTANGLE]->set_toggle_mode(true); + tools[SHAPE_NEW_RECTANGLE]->set_button_group(tg); + tools[SHAPE_NEW_RECTANGLE]->set_tooltip(TTR("Create a new rectangle.")); + tools[SHAPE_NEW_POLYGON] = memnew(ToolButton); toolbar->add_child(tools[SHAPE_NEW_POLYGON]); tools[SHAPE_NEW_POLYGON]->set_toggle_mode(true); @@ -637,6 +644,7 @@ void TileSetEditor::_on_edit_mode_changed(int p_edit_mode) { tools[BITMASK_PASTE]->hide(); tools[BITMASK_CLEAR]->hide(); tools[SHAPE_NEW_POLYGON]->hide(); + tools[SHAPE_NEW_RECTANGLE]->hide(); if (workspace_mode == WORKSPACE_EDIT) { separator_delete->show(); @@ -666,6 +674,7 @@ void TileSetEditor::_on_edit_mode_changed(int p_edit_mode) { tools[BITMASK_PASTE]->hide(); tools[BITMASK_CLEAR]->hide(); tools[SHAPE_NEW_POLYGON]->show(); + tools[SHAPE_NEW_RECTANGLE]->show(); separator_delete->show(); tools[SHAPE_DELETE]->show(); @@ -689,6 +698,7 @@ void TileSetEditor::_on_edit_mode_changed(int p_edit_mode) { tools[BITMASK_PASTE]->show(); tools[BITMASK_CLEAR]->show(); tools[SHAPE_NEW_POLYGON]->hide(); + tools[SHAPE_NEW_RECTANGLE]->hide(); separator_delete->hide(); tools[SHAPE_DELETE]->hide(); @@ -709,6 +719,7 @@ void TileSetEditor::_on_edit_mode_changed(int p_edit_mode) { tools[BITMASK_PASTE]->hide(); tools[BITMASK_CLEAR]->hide(); tools[SHAPE_NEW_POLYGON]->hide(); + tools[SHAPE_NEW_RECTANGLE]->hide(); separator_delete->hide(); tools[SHAPE_DELETE]->hide(); @@ -1430,6 +1441,20 @@ void TileSetEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) { workspace->update(); } } + } else if (tools[SHAPE_NEW_RECTANGLE]->is_pressed()) { + if (mb.is_valid()) { + if (mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { + current_shape.resize(0); + current_shape.push_back(snap_point(shape_anchor)); + current_shape.push_back(snap_point(shape_anchor + Vector2(current_tile_region.size.x, 0))); + current_shape.push_back(snap_point(shape_anchor + current_tile_region.size)); + current_shape.push_back(snap_point(shape_anchor + Vector2(0, current_tile_region.size.y))); + close_shape(shape_anchor); + workspace->update(); + } else if (mb->is_pressed() && mb->get_button_index() == BUTTON_RIGHT) { + workspace->update(); + } + } } } break; default: {} @@ -2548,20 +2573,20 @@ bool TilesetEditorContext::_set(const StringName &p_name, const Variant &p_value tileset_editor->_set_snap_sep(snap); return true; } else if (p_name.operator String().left(5) == "tile_") { - String name = p_name.operator String().right(5); + String name2 = p_name.operator String().right(5); bool v = false; if (tileset_editor->get_current_tile() < 0 || tileset.is_null()) return false; - if (name == "autotile_bitmask_mode") { + if (name2 == "autotile_bitmask_mode") { tileset->set(String::num(tileset_editor->get_current_tile(), 0) + "/autotile/bitmask_mode", p_value, &v); - } else if (name == "subtile_size") { + } else if (name2 == "subtile_size") { tileset->set(String::num(tileset_editor->get_current_tile(), 0) + "/autotile/tile_size", p_value, &v); - } else if (name == "subtile_spacing") { + } else if (name2 == "subtile_spacing") { tileset->set(String::num(tileset_editor->get_current_tile(), 0) + "/autotile/spacing", p_value, &v); } else { - tileset->set(String::num(tileset_editor->get_current_tile(), 0) + "/" + name, p_value, &v); + tileset->set(String::num(tileset_editor->get_current_tile(), 0) + "/" + name2, p_value, &v); } if (v) { tileset->_change_notify(""); @@ -2680,6 +2705,7 @@ void TilesetEditorContext::_bind_methods() { TilesetEditorContext::TilesetEditorContext(TileSetEditor *p_tileset_editor) { tileset_editor = p_tileset_editor; + snap_options_visible = false; } void TileSetEditorPlugin::edit(Object *p_node) { diff --git a/editor/plugins/tile_set_editor_plugin.h b/editor/plugins/tile_set_editor_plugin.h index 1a6b51cdd3..6bbfee8714 100644 --- a/editor/plugins/tile_set_editor_plugin.h +++ b/editor/plugins/tile_set_editor_plugin.h @@ -81,6 +81,7 @@ class TileSetEditor : public HSplitContainer { BITMASK_PASTE, BITMASK_CLEAR, SHAPE_NEW_POLYGON, + SHAPE_NEW_RECTANGLE, SHAPE_DELETE, SHAPE_KEEP_INSIDE_TILE, TOOL_GRID_SNAP, diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index 628c2f714c..7bd26de092 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -393,7 +393,7 @@ void VisualShaderEditor::_preview_select_port(int p_node, int p_port) { if (node->get_output_port_for_preview() == p_port) { p_port = -1; //toggle it } - undo_redo->create_action("Set Uniform Name"); + undo_redo->create_action(TTR("Set Uniform Name")); undo_redo->add_do_method(node.ptr(), "set_output_port_for_preview", p_port); undo_redo->add_undo_method(node.ptr(), "set_output_port_for_preview", node->get_output_port_for_preview()); undo_redo->add_do_method(this, "_update_graph"); @@ -411,7 +411,7 @@ void VisualShaderEditor::_line_edit_changed(const String &p_text, Object *line_e String validated_name = visual_shader->validate_uniform_name(p_text, node); updating = true; - undo_redo->create_action("Set Uniform Name"); + undo_redo->create_action(TTR("Set Uniform Name")); undo_redo->add_do_method(node.ptr(), "set_uniform_name", validated_name); undo_redo->add_undo_method(node.ptr(), "set_uniform_name", node->get_uniform_name()); undo_redo->add_do_method(this, "_update_graph"); @@ -436,7 +436,7 @@ void VisualShaderEditor::_port_edited() { Ref<VisualShaderNode> vsn = visual_shader->get_node(type, editing_node); ERR_FAIL_COND(!vsn.is_valid()); - undo_redo->create_action("Set Input Default Port"); + undo_redo->create_action(TTR("Set Input Default Port")); undo_redo->add_do_method(vsn.ptr(), "set_input_port_default_value", editing_port, value); undo_redo->add_undo_method(vsn.ptr(), "set_input_port_default_value", editing_port, vsn->get_input_port_default_value(editing_port)); undo_redo->add_do_method(this, "_update_graph"); @@ -487,7 +487,7 @@ void VisualShaderEditor::_add_node(int p_idx) { int id_to_use = visual_shader->get_valid_node_id(type); - undo_redo->create_action("Add Node to Visual Shader"); + undo_redo->create_action(TTR("Add Node to Visual Shader")); undo_redo->add_do_method(visual_shader.ptr(), "add_node", type, vsnode, position, id_to_use); undo_redo->add_undo_method(visual_shader.ptr(), "remove_node", type, id_to_use); undo_redo->add_do_method(this, "_update_graph"); @@ -500,7 +500,7 @@ void VisualShaderEditor::_node_dragged(const Vector2 &p_from, const Vector2 &p_t VisualShader::Type type = VisualShader::Type(edit_type->get_selected()); updating = true; - undo_redo->create_action("Node Moved"); + undo_redo->create_action(TTR("Node Moved")); undo_redo->add_do_method(visual_shader.ptr(), "set_node_position", type, p_node, p_to); undo_redo->add_undo_method(visual_shader.ptr(), "set_node_position", type, p_node, p_from); undo_redo->add_do_method(this, "_update_graph"); @@ -521,7 +521,7 @@ void VisualShaderEditor::_connection_request(const String &p_from, int p_from_in return; } - undo_redo->create_action("Nodes Connected"); + undo_redo->create_action(TTR("Nodes Connected")); List<VisualShader::Connection> conns; visual_shader->get_node_connections(type, &conns); @@ -550,7 +550,7 @@ void VisualShaderEditor::_disconnection_request(const String &p_from, int p_from int to = p_to.to_int(); //updating = true; seems graph edit can handle this, no need to protect - undo_redo->create_action("Nodes Disconnected"); + undo_redo->create_action(TTR("Nodes Disconnected")); undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, from, p_from_index, to, p_to_index); undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, from, p_from_index, to, p_to_index); undo_redo->add_do_method(this, "_update_graph"); @@ -566,7 +566,7 @@ void VisualShaderEditor::_delete_request(int which) { VisualShader::Type type = VisualShader::Type(edit_type->get_selected()); - undo_redo->create_action("Delete Node"); + undo_redo->create_action(TTR("Delete Node")); undo_redo->add_do_method(visual_shader.ptr(), "remove_node", type, which); undo_redo->add_undo_method(visual_shader.ptr(), "add_node", type, visual_shader->get_node(type, which), visual_shader->get_node_position(type, which), which); @@ -671,7 +671,7 @@ void VisualShaderEditor::_duplicate_nodes() { if (nodes.empty()) return; - undo_redo->create_action("Duplicate Nodes"); + undo_redo->create_action(TTR("Duplicate Nodes")); int base_id = visual_shader->get_valid_node_id(type); int id_from = base_id; @@ -732,7 +732,7 @@ void VisualShaderEditor::_input_select_item(Ref<VisualShaderNodeInput> input, St bool type_changed = input->get_input_type_by_name(name) != input->get_input_type_by_name(prev_name); UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo(); - undo_redo->create_action("Visual Shader Input Type Changed"); + undo_redo->create_action(TTR("Visual Shader Input Type Changed")); undo_redo->add_do_method(input.ptr(), "set_input_name", name); undo_redo->add_undo_method(input.ptr(), "set_input_name", prev_name); @@ -972,7 +972,7 @@ public: UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo(); updating = true; - undo_redo->create_action("Edit Visual Property: " + prop, UndoRedo::MERGE_ENDS); + undo_redo->create_action(TTR("Edit Visual Property") + ": " + prop, UndoRedo::MERGE_ENDS); undo_redo->add_do_property(node.ptr(), prop, p_value); undo_redo->add_undo_property(node.ptr(), prop, node->get(prop)); undo_redo->commit_action(); @@ -1093,7 +1093,7 @@ void EditorPropertyShaderMode::_option_selected(int p_which) { return; UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo(); - undo_redo->create_action("Visual Shader Mode Changed"); + undo_redo->create_action(TTR("Visual Shader Mode Changed")); //do is easy undo_redo->add_do_method(visual_shader.ptr(), "set_mode", p_which); undo_redo->add_undo_method(visual_shader.ptr(), "set_mode", visual_shader->get_mode()); @@ -1116,8 +1116,8 @@ void EditorPropertyShaderMode::_option_selected(int p_which) { VisualShader::Type type = VisualShader::Type(i); Vector<int> nodes = visual_shader->get_node_list(type); - for (int i = 0; i < nodes.size(); i++) { - Ref<VisualShaderNodeInput> input = visual_shader->get_node(type, nodes[i]); + for (int j = 0; j < nodes.size(); j++) { + Ref<VisualShaderNodeInput> input = visual_shader->get_node(type, nodes[j]); if (!input.is_valid()) { continue; } diff --git a/editor/project_export.cpp b/editor/project_export.cpp index ec64d76b18..831ebde3a6 100644 --- a/editor/project_export.cpp +++ b/editor/project_export.cpp @@ -972,10 +972,15 @@ void ProjectExportDialog::_export_project_to_path(const String &p_path) { Error err = platform->export_project(current, export_debug->is_pressed(), p_path, 0); if (err != OK) { - error_dialog->set_text(TTR("Export templates for this platform are missing/corrupted:") + " " + platform->get_name()); + if (err == ERR_FILE_NOT_FOUND) { + error_dialog->set_text(vformat(TTR("Failed to export the project for platform '%s'.\nExport templates seem to be missing or invalid."), platform->get_name())); + } else { // Assume misconfiguration. FIXME: Improve error handling and preset config validation. + error_dialog->set_text(vformat(TTR("Failed to export the project for platform '%s'.\nThis might be due to a configuration issue in the export preset or your export settings."), platform->get_name())); + } + + ERR_PRINTS(vformat("Failed to export the project for platform '%s'.", platform->get_name())); error_dialog->show(); error_dialog->popup_centered_minsize(Size2(300, 80)); - ERR_PRINT("Failed to export project"); } } diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp index 7ce4029476..a3bcfa6e70 100644 --- a/editor/project_manager.cpp +++ b/editor/project_manager.cpp @@ -434,22 +434,22 @@ private: if (mode == MODE_RENAME) { - String dir = _test_path(); - if (dir == "") { + String dir2 = _test_path(); + if (dir2 == "") { set_message(TTR("Invalid project path (changed anything?)."), MESSAGE_ERROR); return; } ProjectSettings *current = memnew(ProjectSettings); - int err = current->setup(dir, ""); + int err = current->setup(dir2, ""); if (err != OK) { set_message(vformat(TTR("Couldn't load project.godot in project path (error %d). It may be missing or corrupted."), err), MESSAGE_ERROR); } else { ProjectSettings::CustomMap edited_settings; edited_settings["application/config/name"] = project_name->get_text(); - if (current->save_custom(dir.plus_file("project.godot"), edited_settings, Vector<String>(), true) != OK) { + if (current->save_custom(dir2.plus_file("project.godot"), edited_settings, Vector<String>(), true) != OK) { set_message(TTR("Couldn't edit project.godot in project path."), MESSAGE_ERROR); } } @@ -1422,6 +1422,7 @@ void ProjectManager::_on_projects_updated() { } void ProjectManager::_on_project_created(const String &dir) { + project_filter->clear(); bool has_already = false; for (int i = 0; i < scroll_children->get_child_count(); i++) { HBoxContainer *hb = Object::cast_to<HBoxContainer>(scroll_children->get_child(i)); @@ -1526,6 +1527,13 @@ void ProjectManager::_open_selected_projects_ask() { } int config_version = (int)cf->get_value("", "config_version", 0); + + // Check if the config_version property was empty or 0 + if (config_version == 0) { + ask_update_settings->set_text(vformat(TTR("The following project settings file does not specify the version of Godot through which it was created.\n\n%s\n\nIf you proceed with opening it, it will be converted to Godot's current configuration file format.\nWarning: You will not be able to open the project with previous versions of the engine anymore."), conf)); + ask_update_settings->popup_centered_minsize(); + return; + } // Check if we need to convert project settings from an earlier engine version if (config_version < ProjectSettings::CONFIG_VERSION) { ask_update_settings->set_text(vformat(TTR("The following project settings file was generated by an older engine version, and needs to be converted for this version:\n\n%s\n\nDo you want to convert it?\nWarning: You will not be able to open the project with previous versions of the engine anymore."), conf)); @@ -1888,13 +1896,12 @@ ProjectManager::ProjectManager() { Panel *panel = memnew(Panel); gui_base->add_child(panel); panel->set_anchors_and_margins_preset(Control::PRESET_WIDE); + panel->add_style_override("panel", gui_base->get_stylebox("Background", "EditorStyles")); VBoxContainer *vb = memnew(VBoxContainer); panel->add_child(vb); - vb->set_anchors_and_margins_preset(Control::PRESET_WIDE, Control::PRESET_MODE_MINSIZE, 20 * EDSCALE); - vb->set_margin(MARGIN_TOP, 4 * EDSCALE); - vb->set_margin(MARGIN_BOTTOM, -4 * EDSCALE); - vb->add_constant_override("separation", 15 * EDSCALE); + vb->set_anchors_and_margins_preset(Control::PRESET_WIDE, Control::PRESET_MODE_MINSIZE, 8 * EDSCALE); + vb->add_constant_override("separation", 8 * EDSCALE); String cp; cp += 0xA9; @@ -1902,11 +1909,9 @@ ProjectManager::ProjectManager() { HBoxContainer *top_hb = memnew(HBoxContainer); vb->add_child(top_hb); - CenterContainer *ccl = memnew(CenterContainer); Label *l = memnew(Label); l->set_text(VERSION_NAME + String(" - ") + TTR("Project Manager")); - ccl->add_child(l); - top_hb->add_child(ccl); + top_hb->add_child(l); top_hb->add_spacer(); l = memnew(Label); String hash = String(VERSION_HASH); @@ -2053,6 +2058,8 @@ ProjectManager::ProjectManager() { settings_hb->set_h_grow_direction(Control::GROW_DIRECTION_BEGIN); language_btn = memnew(OptionButton); + language_btn->set_flat(true); + language_btn->set_focus_mode(Control::FOCUS_NONE); Vector<String> editor_languages; List<PropertyInfo> editor_settings_properties; @@ -2230,3 +2237,9 @@ ProjectListFilter::ProjectListFilter() { has_search_box = false; } + +void ProjectListFilter::clear() { + if (has_search_box) { + search_box->clear(); + } +} diff --git a/editor/project_manager.h b/editor/project_manager.h index 6eb55871e4..1fdd7dbe06 100644 --- a/editor/project_manager.h +++ b/editor/project_manager.h @@ -154,6 +154,7 @@ public: FilterOption get_filter_option(); void set_filter_option(FilterOption); ProjectListFilter(); + void clear(); }; #endif // PROJECT_MANAGER_H diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp index cc33550ac9..1c6359a46b 100644 --- a/editor/project_settings_editor.cpp +++ b/editor/project_settings_editor.cpp @@ -712,7 +712,7 @@ void ProjectSettingsEditor::_update_actions() { if (event.is_null()) continue; - TreeItem *action = input_editor->create_item(item); + TreeItem *action2 = input_editor->create_item(item); Ref<InputEventKey> k = event; if (k.is_valid()) { @@ -727,8 +727,8 @@ void ProjectSettingsEditor::_update_actions() { if (k->get_control()) str = TTR("Control+") + str; - action->set_text(0, str); - action->set_icon(0, get_icon("Keyboard", "EditorIcons")); + action2->set_text(0, str); + action2->set_icon(0, get_icon("Keyboard", "EditorIcons")); } Ref<InputEventJoypadButton> jb = event; @@ -741,8 +741,8 @@ void ProjectSettingsEditor::_update_actions() { else str += "."; - action->set_text(0, str); - action->set_icon(0, get_icon("JoyButton", "EditorIcons")); + action2->set_text(0, str); + action2->set_icon(0, get_icon("JoyButton", "EditorIcons")); } Ref<InputEventMouseButton> mb = event; @@ -758,8 +758,8 @@ void ProjectSettingsEditor::_update_actions() { default: str += TTR("Button") + " " + itos(mb->get_button_index()) + "."; } - action->set_text(0, str); - action->set_icon(0, get_icon("Mouse", "EditorIcons")); + action2->set_text(0, str); + action2->set_icon(0, get_icon("Mouse", "EditorIcons")); } Ref<InputEventJoypadMotion> jm = event; @@ -770,14 +770,14 @@ void ProjectSettingsEditor::_update_actions() { int n = 2 * ax + (jm->get_axis_value() < 0 ? 0 : 1); String desc = _axis_names[n]; String str = _get_device_string(jm->get_device()) + ", " + TTR("Axis") + " " + itos(ax) + " " + (jm->get_axis_value() < 0 ? "-" : "+") + desc + "."; - action->set_text(0, str); - action->set_icon(0, get_icon("JoyAxis", "EditorIcons")); + action2->set_text(0, str); + action2->set_icon(0, get_icon("JoyAxis", "EditorIcons")); } - action->set_metadata(0, i); - action->set_meta("__input", event); + action2->set_metadata(0, i); + action2->set_meta("__input", event); - action->add_button(2, get_icon("Edit", "EditorIcons"), 3, false, TTR("Edit")); - action->add_button(2, get_icon("Remove", "EditorIcons"), 2, false, TTR("Remove")); + action2->add_button(2, get_icon("Edit", "EditorIcons"), 3, false, TTR("Edit")); + action2->add_button(2, get_icon("Remove", "EditorIcons"), 2, false, TTR("Remove")); } } @@ -1034,8 +1034,8 @@ void ProjectSettingsEditor::_copy_to_platform_about_to_show() { String custom = EditorExport::get_singleton()->get_export_preset(i)->get_custom_features(); Vector<String> custom_list = custom.split(","); - for (int i = 0; i < custom_list.size(); i++) { - String f = custom_list[i].strip_edges(); + for (int j = 0; j < custom_list.size(); j++) { + String f = custom_list[j].strip_edges(); if (f != String()) { presets.insert(f); } @@ -1543,10 +1543,10 @@ void ProjectSettingsEditor::_update_translations() { PoolStringArray selected = remaps[keys[i]]; for (int j = 0; j < selected.size(); j++) { - String s = selected[j]; - int qp = s.find_last(":"); - String path = s.substr(0, qp); - String locale = s.substr(qp + 1, s.length()); + String s2 = selected[j]; + int qp = s2.find_last(":"); + String path = s2.substr(0, qp); + String locale = s2.substr(qp + 1, s2.length()); TreeItem *t2 = translation_remap_options->create_item(root2); t2->set_editable(0, false); diff --git a/editor/property_editor.cpp b/editor/property_editor.cpp index 46e2bb18fe..c45a97800c 100644 --- a/editor/property_editor.cpp +++ b/editor/property_editor.cpp @@ -905,8 +905,8 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant:: List<StringName> inheritors; ClassDB::get_inheriters_from_class(base.strip_edges(), &inheritors); - for (int i = 0; i < custom_resources.size(); i++) { - inheritors.push_back(custom_resources[i].name); + for (int j = 0; j < custom_resources.size(); j++) { + inheritors.push_back(custom_resources[j].name); } List<StringName>::Element *E = inheritors.front(); @@ -915,17 +915,17 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant:: E = E->next(); } - for (Set<String>::Element *E = valid_inheritors.front(); E; E = E->next()) { - String t = E->get(); + for (Set<String>::Element *j = valid_inheritors.front(); j; j = j->next()) { + String t = j->get(); bool is_custom_resource = false; Ref<Texture> icon; if (!custom_resources.empty()) { - for (int i = 0; i < custom_resources.size(); i++) { - if (custom_resources[i].name == t) { + for (int k = 0; k < custom_resources.size(); k++) { + if (custom_resources[k].name == t) { is_custom_resource = true; - if (custom_resources[i].icon.is_valid()) - icon = custom_resources[i].icon; + if (custom_resources[k].icon.is_valid()) + icon = custom_resources[k].icon; break; } } diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index 738d747956..d931d5bb37 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -583,7 +583,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { return; } - editor_data->get_undo_redo().create_action("Make node as Root"); + editor_data->get_undo_redo().create_action(TTR("Make node as Root")); editor_data->get_undo_redo().add_do_method(node->get_parent(), "remove_child", node); editor_data->get_undo_redo().add_do_method(root->get_parent(), "remove_child", root); editor_data->get_undo_redo().add_do_method(node, "add_child", root); @@ -849,7 +849,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { } } - editor_data->get_undo_redo().create_action("New Scene Root"); + editor_data->get_undo_redo().create_action(TTR("New Scene Root")); editor_data->get_undo_redo().add_do_method(editor, "set_edited_scene", new_node); editor_data->get_undo_redo().add_do_method(scene_tree, "update_tree"); editor_data->get_undo_redo().add_do_reference(new_node); @@ -1152,17 +1152,17 @@ void SceneTreeDock::perform_node_renames(Node *p_base, List<Pair<NodePath, NodeP if (p.get_type() == Variant::NODE_PATH) { // Goes through all paths to check if its matching - for (List<Pair<NodePath, NodePath> >::Element *E = p_renames->front(); E; E = E->next()) { + for (List<Pair<NodePath, NodePath> >::Element *F = p_renames->front(); F; F = F->next()) { NodePath root_path = p_base->get_path(); - NodePath rel_path_old = root_path.rel_path_to(E->get().first); + NodePath rel_path_old = root_path.rel_path_to(F->get().first); - NodePath rel_path_new = E->get().second; + NodePath rel_path_new = F->get().second; // if not empty, get new relative path - if (E->get().second != NodePath()) { - rel_path_new = root_path.rel_path_to(E->get().second); + if (F->get().second != NodePath()) { + rel_path_new = root_path.rel_path_to(F->get().second); } // if old path detected, then it needs to be replaced with the new one @@ -1233,11 +1233,11 @@ void SceneTreeDock::perform_node_renames(Node *p_base, List<Pair<NodePath, NodeP if (!ran.has(i)) continue; //channel was removed - for (List<Pair<NodePath, NodePath> >::Element *E = p_renames->front(); E; E = E->next()) { + for (List<Pair<NodePath, NodePath> >::Element *F = p_renames->front(); F; F = F->next()) { - if (E->get().first == old_np) { + if (F->get().first == old_np) { - if (E->get().second == NodePath()) { + if (F->get().second == NodePath()) { //will be erased int idx = 0; @@ -1262,7 +1262,7 @@ void SceneTreeDock::perform_node_renames(Node *p_base, List<Pair<NodePath, NodeP } else { //will be renamed - NodePath rel_path = new_root_path.rel_path_to(E->get().second); + NodePath rel_path = new_root_path.rel_path_to(F->get().second); NodePath new_path = NodePath(rel_path.get_names(), track_np.get_subnames(), false); if (new_path == track_np) @@ -1602,9 +1602,9 @@ void SceneTreeDock::_delete_confirm() { List<Node *> owned; n->get_owned_by(n->get_owner(), &owned); Array owners; - for (List<Node *>::Element *E = owned.front(); E; E = E->next()) { + for (List<Node *>::Element *F = owned.front(); F; F = F->next()) { - owners.push_back(E->get()); + owners.push_back(F->get()); } editor_data->get_undo_redo().add_do_method(n->get_parent(), "remove_child", n); diff --git a/editor/script_create_dialog.cpp b/editor/script_create_dialog.cpp index 6a3ed1c5e0..5ab0efaee3 100644 --- a/editor/script_create_dialog.cpp +++ b/editor/script_create_dialog.cpp @@ -255,8 +255,8 @@ void ScriptCreateDialog::_lang_changed(int l) { // change extension by selected language List<String> extensions; // get all possible extensions for script - for (int l = 0; l < language_menu->get_item_count(); l++) { - ScriptServer::get_language(l)->get_recognized_extensions(&extensions); + for (int m = 0; m < language_menu->get_item_count(); m++) { + ScriptServer::get_language(m)->get_recognized_extensions(&extensions); } for (List<String>::Element *E = extensions.front(); E; E = E->next()) { diff --git a/editor/script_editor_debugger.cpp b/editor/script_editor_debugger.cpp index 5f6459045a..303d10d768 100644 --- a/editor/script_editor_debugger.cpp +++ b/editor/script_editor_debugger.cpp @@ -777,7 +777,7 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da for (int i = 0; i < scc; i += 3) { String script = p_data[2 + i]; - String method = p_data[3 + i]; + String method2 = p_data[3 + i]; int line = p_data[4 + i]; TreeItem *stack_trace = error_tree->create_item(error); @@ -791,7 +791,7 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da stack_trace->set_text_align(0, TreeItem::ALIGN_LEFT); error->set_metadata(0, meta); } - stack_trace->set_text(1, script.get_file() + ":" + itos(line) + " @ " + method + "()"); + stack_trace->set_text(1, script.get_file() + ":" + itos(line) + " @ " + method2 + "()"); } if (warning) @@ -859,18 +859,18 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da c.items.resize(values.size() / 2); c.total_time = 0; c.signature = "categ::" + name; - for (int i = 0; i < values.size(); i += 2) { + for (int j = 0; j < values.size(); j += 2) { EditorProfiler::Metric::Category::Item item; item.calls = 1; item.line = 0; - item.name = values[i]; - item.self = values[i + 1]; + item.name = values[j]; + item.self = values[j + 1]; item.total = item.self; item.signature = "categ::" + name + "::" + item.name; item.name = item.name.capitalize(); c.total_time += item.total; - c.items.write[i / 2] = item; + c.items.write[j / 2] = item; } metric.categories.push_back(c); } @@ -1002,13 +1002,13 @@ void ScriptEditorDebugger::_performance_draw() { float m = perf_max[pi]; if (m == 0) m = 0.00001; - float h = E->get()[pi] / m; - h = (1.0 - h) * r.size.y; + float h2 = E->get()[pi] / m; + h2 = (1.0 - h2) * r.size.y; c.a = 0.7; if (E != perf_history.front()) - perf_draw->draw_line(r.position + Point2(from, h), r.position + Point2(from + spacing, prev), c, 2.0); - prev = h; + perf_draw->draw_line(r.position + Point2(from, h2), r.position + Point2(from + spacing, prev), c, 2.0); + prev = h2; E = E->next(); from -= spacing; } @@ -1536,14 +1536,14 @@ void ScriptEditorDebugger::_property_changed(Object *p_base, const StringName &p int pathid = _get_res_path_cache(respath); if (p_value.is_ref()) { - Ref<Resource> res = p_value; - if (res.is_valid() && res->get_path() != String()) { + Ref<Resource> res2 = p_value; + if (res2.is_valid() && res2->get_path() != String()) { Array msg; msg.push_back("live_res_prop_res"); msg.push_back(pathid); msg.push_back(p_property); - msg.push_back(res->get_path()); + msg.push_back(res2->get_path()); ppeer->put_var(msg); } } else { diff --git a/editor/settings_config_dialog.cpp b/editor/settings_config_dialog.cpp index ecd35cb930..611067214d 100644 --- a/editor/settings_config_dialog.cpp +++ b/editor/settings_config_dialog.cpp @@ -282,7 +282,7 @@ void EditorSettingsDialog::_shortcut_button_pressed(Object *p_item, int p_column if (!sc.is_valid()) return; //pointless, there is nothing - undo_redo->create_action("Erase Shortcut"); + undo_redo->create_action(TTR("Erase Shortcut")); undo_redo->add_do_method(sc.ptr(), "set_shortcut", Ref<InputEvent>()); undo_redo->add_undo_method(sc.ptr(), "set_shortcut", sc->get_shortcut()); undo_redo->add_do_method(this, "_update_shortcuts"); @@ -296,7 +296,7 @@ void EditorSettingsDialog::_shortcut_button_pressed(Object *p_item, int p_column Ref<InputEvent> original = sc->get_meta("original"); - undo_redo->create_action("Restore Shortcut"); + undo_redo->create_action(TTR("Restore Shortcut")); undo_redo->add_do_method(sc.ptr(), "set_shortcut", original); undo_redo->add_undo_method(sc.ptr(), "set_shortcut", sc->get_shortcut()); undo_redo->add_do_method(this, "_update_shortcuts"); @@ -344,7 +344,7 @@ void EditorSettingsDialog::_press_a_key_confirm() { Ref<ShortCut> sc = EditorSettings::get_singleton()->get_shortcut(shortcut_configured); - undo_redo->create_action("Change Shortcut '" + shortcut_configured + "'"); + undo_redo->create_action(TTR("Change Shortcut") + " '" + shortcut_configured + "'"); undo_redo->add_do_method(sc.ptr(), "set_shortcut", ie); undo_redo->add_undo_method(sc.ptr(), "set_shortcut", sc->get_shortcut()); undo_redo->add_do_method(this, "_update_shortcuts"); diff --git a/editor/spatial_editor_gizmos.cpp b/editor/spatial_editor_gizmos.cpp index 4f1928d20c..7a4b7d091f 100644 --- a/editor/spatial_editor_gizmos.cpp +++ b/editor/spatial_editor_gizmos.cpp @@ -1235,8 +1235,8 @@ void CameraSpatialGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_idx Vector3 s[2] = { gi.xform(ray_from), gi.xform(ray_from + ray_dir * 4096) }; if (camera->get_projection() == Camera::PROJECTION_PERSPECTIVE) { - Transform gt = camera->get_global_transform(); - float a = _find_closest_angle_to_half_pi_arc(s[0], s[1], 1.0, gt); + Transform gt2 = camera->get_global_transform(); + float a = _find_closest_angle_to_half_pi_arc(s[0], s[1], 1.0, gt2); camera->set("fov", a * 2.0); } else { @@ -2414,8 +2414,8 @@ void ParticlesGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); ur->create_action(TTR("Change Particles AABB")); - ur->add_do_method(particles, "set_custom_aabb", particles->get_visibility_aabb()); - ur->add_undo_method(particles, "set_custom_aabb", p_restore); + ur->add_do_method(particles, "set_visibility_aabb", particles->get_visibility_aabb()); + ur->add_undo_method(particles, "set_visibility_aabb", p_restore); ur->commit_action(); } @@ -3019,20 +3019,20 @@ Variant CollisionShapeSpatialGizmoPlugin::get_handle_value(EditorSpatialGizmo *p if (Object::cast_to<CapsuleShape>(*s)) { - Ref<CapsuleShape> cs = s; - return p_idx == 0 ? cs->get_radius() : cs->get_height(); + Ref<CapsuleShape> cs2 = s; + return p_idx == 0 ? cs2->get_radius() : cs2->get_height(); } if (Object::cast_to<CylinderShape>(*s)) { - Ref<CylinderShape> cs = s; - return p_idx == 0 ? cs->get_radius() : cs->get_height(); + Ref<CylinderShape> cs2 = s; + return p_idx == 0 ? cs2->get_radius() : cs2->get_height(); } if (Object::cast_to<RayShape>(*s)) { - Ref<RayShape> cs = s; - return cs->get_length(); + Ref<RayShape> cs2 = s; + return cs2->get_length(); } return Variant(); @@ -3098,26 +3098,26 @@ void CollisionShapeSpatialGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, i Vector3 axis; axis[p_idx == 0 ? 0 : 2] = 1.0; - Ref<CapsuleShape> cs = s; + Ref<CapsuleShape> cs2 = s; Vector3 ra, rb; Geometry::get_closest_points_between_segments(Vector3(), axis * 4096, sg[0], sg[1], ra, rb); float d = axis.dot(ra); if (p_idx == 1) - d -= cs->get_radius(); + d -= cs2->get_radius(); if (d < 0.001) d = 0.001; if (p_idx == 0) - cs->set_radius(d); + cs2->set_radius(d); else if (p_idx == 1) - cs->set_height(d * 2.0); + cs2->set_height(d * 2.0); } if (Object::cast_to<CylinderShape>(*s)) { Vector3 axis; axis[p_idx == 0 ? 0 : 1] = 1.0; - Ref<CylinderShape> cs = s; + Ref<CylinderShape> cs2 = s; Vector3 ra, rb; Geometry::get_closest_points_between_segments(Vector3(), axis * 4096, sg[0], sg[1], ra, rb); float d = axis.dot(ra); @@ -3126,9 +3126,9 @@ void CollisionShapeSpatialGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, i d = 0.001; if (p_idx == 0) - cs->set_radius(d); + cs2->set_radius(d); else if (p_idx == 1) - cs->set_height(d * 2.0); + cs2->set_height(d * 2.0); } } void CollisionShapeSpatialGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) { @@ -3328,9 +3328,9 @@ void CollisionShapeSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { if (Object::cast_to<CapsuleShape>(*s)) { - Ref<CapsuleShape> cs = s; - float radius = cs->get_radius(); - float height = cs->get_height(); + Ref<CapsuleShape> cs2 = s; + float radius = cs2->get_radius(); + float height = cs2->get_height(); Vector<Vector3> points; @@ -3396,16 +3396,16 @@ void CollisionShapeSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { p_gizmo->add_collision_segments(collision_segments); Vector<Vector3> handles; - handles.push_back(Vector3(cs->get_radius(), 0, 0)); - handles.push_back(Vector3(0, 0, cs->get_height() * 0.5 + cs->get_radius())); + handles.push_back(Vector3(cs2->get_radius(), 0, 0)); + handles.push_back(Vector3(0, 0, cs2->get_height() * 0.5 + cs2->get_radius())); p_gizmo->add_handles(handles, handles_material); } if (Object::cast_to<CylinderShape>(*s)) { - Ref<CylinderShape> cs = s; - float radius = cs->get_radius(); - float height = cs->get_height(); + Ref<CylinderShape> cs2 = s; + float radius = cs2->get_radius(); + float height = cs2->get_height(); Vector<Vector3> points; @@ -3457,8 +3457,8 @@ void CollisionShapeSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { p_gizmo->add_collision_segments(collision_segments); Vector<Vector3> handles; - handles.push_back(Vector3(cs->get_radius(), 0, 0)); - handles.push_back(Vector3(0, cs->get_height() * 0.5, 0)); + handles.push_back(Vector3(cs2->get_radius(), 0, 0)); + handles.push_back(Vector3(0, cs2->get_height() * 0.5, 0)); p_gizmo->add_handles(handles, handles_material); } @@ -3503,23 +3503,23 @@ void CollisionShapeSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { Geometry::MeshData md; Error err = QuickHull::build(varr, md); if (err == OK) { - Vector<Vector3> points; - points.resize(md.edges.size() * 2); + Vector<Vector3> points2; + points2.resize(md.edges.size() * 2); for (int i = 0; i < md.edges.size(); i++) { - points.write[i * 2 + 0] = md.vertices[md.edges[i].a]; - points.write[i * 2 + 1] = md.vertices[md.edges[i].b]; + points2.write[i * 2 + 0] = md.vertices[md.edges[i].a]; + points2.write[i * 2 + 1] = md.vertices[md.edges[i].b]; } - p_gizmo->add_lines(points, material); - p_gizmo->add_collision_segments(points); + p_gizmo->add_lines(points2, material); + p_gizmo->add_collision_segments(points2); } } } if (Object::cast_to<ConcavePolygonShape>(*s)) { - Ref<ConcavePolygonShape> cs = s; - Ref<ArrayMesh> mesh = cs->get_debug_mesh()->duplicate(); + Ref<ConcavePolygonShape> cs2 = s; + Ref<ArrayMesh> mesh = cs2->get_debug_mesh()->duplicate(); mesh->surface_set_material(0, material); p_gizmo->add_mesh(mesh); } @@ -3584,10 +3584,10 @@ void CollisionPolygonSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { //// NavigationMeshSpatialGizmoPlugin::NavigationMeshSpatialGizmoPlugin() { - create_material("navigation_material", EDITOR_DEF("editors/3d_gizmos/gizmo_colors/navigation_edge", Color(0.5, 1, 1))); - create_material("navigation_material", EDITOR_DEF("editors/3d_gizmos/gizmo_colors/navigation_edge_disabled", Color(0.7, 0.7, 0.7))); - create_material("navigation_material", EDITOR_DEF("editors/3d_gizmos/gizmo_colors/navigation_solid", Color(0.5, 1, 1, 0.4))); - create_material("navigation_material", EDITOR_DEF("editors/3d_gizmos/gizmo_colors/navigation_solid_disabled", Color(0.7, 0.7, 0.7, 0.4))); + create_material("navigation_edge_material", EDITOR_DEF("editors/3d_gizmos/gizmo_colors/navigation_edge", Color(0.5, 1, 1))); + create_material("navigation_edge_material_disabled", EDITOR_DEF("editors/3d_gizmos/gizmo_colors/navigation_edge_disabled", Color(0.7, 0.7, 0.7))); + create_material("navigation_solid_material", EDITOR_DEF("editors/3d_gizmos/gizmo_colors/navigation_solid", Color(0.5, 1, 1, 0.4))); + create_material("navigation_solid_material_disabled", EDITOR_DEF("editors/3d_gizmos/gizmo_colors/navigation_solid_disabled", Color(0.7, 0.7, 0.7, 0.4))); } bool NavigationMeshSpatialGizmoPlugin::has_gizmo(Spatial *p_spatial) { @@ -3602,10 +3602,10 @@ void NavigationMeshSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { NavigationMeshInstance *navmesh = Object::cast_to<NavigationMeshInstance>(p_gizmo->get_spatial_node()); - Ref<Material> edge_material = get_material("navigation_material", p_gizmo); - Ref<Material> edge_material_disabled = get_material("navigation_material", p_gizmo); - Ref<Material> solid_material = get_material("navigation_material", p_gizmo); - Ref<Material> solid_material_disabled = get_material("navigation_material", p_gizmo); + Ref<Material> edge_material = get_material("navigation_edge_material", p_gizmo); + Ref<Material> edge_material_disabled = get_material("navigation_edge_material_disabled", p_gizmo); + Ref<Material> solid_material = get_material("navigation_solid_material", p_gizmo); + Ref<Material> solid_material_disabled = get_material("navigation_solid_material_disabled", p_gizmo); p_gizmo->clear(); Ref<NavigationMesh> navmeshie = navmesh->get_navigation_mesh(); @@ -3652,11 +3652,11 @@ void NavigationMeshSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { if (ek.from < ek.to) SWAP(ek.from, ek.to); - Map<_EdgeKey, bool>::Element *E = edge_map.find(ek); + Map<_EdgeKey, bool>::Element *F = edge_map.find(ek); - if (E) { + if (F) { - E->get() = false; + F->get() = false; } else { diff --git a/editor/translations/af.po b/editor/translations/af.po index 58d83b6c78..fa210f0894 100644 --- a/editor/translations/af.po +++ b/editor/translations/af.po @@ -552,22 +552,14 @@ msgstr "Zoem Uit" msgid "Reset Zoom" msgstr "Herset Zoem" -#: editor/code_editor.cpp -msgid "Warnings:" +#: editor/code_editor.cpp modules/mono/editor/mono_bottom_panel.cpp +msgid "Warnings" msgstr "" #: editor/code_editor.cpp -msgid "Font Size:" +msgid "Line and column numbers." msgstr "" -#: editor/code_editor.cpp -msgid "Line:" -msgstr "Reël:" - -#: editor/code_editor.cpp -msgid "Col:" -msgstr "Kol:" - #: editor/connections_dialog.cpp msgid "Method in target Node must be specified!" msgstr "Metode in teiken Nodus moet gespesifiseer word!" @@ -878,8 +870,8 @@ msgstr "Skrap gekose lêers?" #: editor/dependency_editor.cpp editor/editor_audio_buses.cpp #: editor/editor_file_dialog.cpp editor/editor_node.cpp #: editor/filesystem_dock.cpp editor/plugins/item_list_editor_plugin.cpp -#: editor/project_export.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_dock.cpp +#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp +#: editor/project_settings_editor.cpp editor/scene_tree_dock.cpp msgid "Delete" msgstr "Skrap" @@ -1138,8 +1130,9 @@ msgid "Add Bus" msgstr "Voeg Bus By" #: editor/editor_audio_buses.cpp -msgid "Create a new Bus Layout." -msgstr "Skep 'n nuwe Bus Uitleg." +#, fuzzy +msgid "Add a new Audio Bus to this layout." +msgstr "Stoor Oudio-Bus Uitleg As..." #: editor/editor_audio_buses.cpp editor/editor_properties.cpp #: editor/plugins/animation_player_editor_plugin.cpp editor/property_editor.cpp @@ -1168,6 +1161,10 @@ msgstr "Laai Verstek" msgid "Load the default Bus Layout." msgstr "Laai die verstek Bus Uitleg." +#: editor/editor_audio_buses.cpp +msgid "Create a new Bus Layout." +msgstr "Skep 'n nuwe Bus Uitleg." + #: editor/editor_autoload_settings.cpp msgid "Invalid name." msgstr "Ongeldige naam." @@ -2375,7 +2372,7 @@ msgid "Save & Restart" msgstr "" #: editor/editor_node.cpp -msgid "Spins when the editor window repaints!" +msgid "Spins when the editor window redraws." msgstr "" #: editor/editor_node.cpp @@ -3445,23 +3442,6 @@ msgid "Create Polygon" msgstr "Skep Intekening" #: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Edit Polygon" -msgstr "Skep Intekening" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Insert Point" -msgstr "" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Edit Polygon (Remove Point)" -msgstr "" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Remove Polygon And Point" -msgstr "" - -#: editor/plugins/abstract_polygon_2d_editor.cpp #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #, fuzzy @@ -3480,6 +3460,23 @@ msgstr "" msgid "Erase points." msgstr "" +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Edit Polygon" +msgstr "Skep Intekening" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Insert Point" +msgstr "" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Edit Polygon (Remove Point)" +msgstr "" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Remove Polygon And Point" +msgstr "" + #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #: editor/plugins/animation_player_editor_plugin.cpp @@ -4279,6 +4276,16 @@ msgid "Move CanvasItem" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp +msgid "Presets for the anchors and margins values of a Control node." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp +msgid "" +"Children of containers have their anchors and margins values overridden by " +"their parent." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp msgid "Anchors only" msgstr "" @@ -5181,6 +5188,12 @@ msgid "Create UV Map" msgstr "" #: editor/plugins/polygon_2d_editor_plugin.cpp +msgid "" +"Polygon 2D has internal vertices, so it can no longer be edited in the " +"viewport." +msgstr "" + +#: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Create Polygon & UV" msgstr "" @@ -6293,7 +6306,7 @@ msgid "Post" msgstr "" #: editor/plugins/spatial_editor_plugin.cpp -msgid "Name-less gizmo" +msgid "Nameless gizmo" msgstr "" #: editor/plugins/sprite_editor_plugin.cpp @@ -6371,8 +6384,14 @@ msgid "(empty)" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animations" -msgstr "" +#, fuzzy +msgid "Animations:" +msgstr "Animasie Zoem." + +#: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "New Animation" +msgstr "Optimaliseer Animasie" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed (FPS):" @@ -6383,8 +6402,9 @@ msgid "Loop" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animation Frames" -msgstr "" +#, fuzzy +msgid "Animation Frames:" +msgstr "Animasie Zoem." #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Insert Empty (Before)" @@ -7185,6 +7205,19 @@ msgstr "" #: editor/project_manager.cpp msgid "" +"The following project settings file does not specify the version of Godot " +"through which it was created.\n" +"\n" +"%s\n" +"\n" +"If you proceed with opening it, it will be converted to Godot's current " +"configuration file format.\n" +"Warning: You will not be able to open the project with previous versions of " +"the engine anymore." +msgstr "" + +#: editor/project_manager.cpp +msgid "" "The following project settings file was generated by an older engine " "version, and needs to be converted for this version:\n" "\n" @@ -8677,10 +8710,6 @@ msgid "Build Project" msgstr "" #: modules/mono/editor/mono_bottom_panel.cpp -msgid "Warnings" -msgstr "" - -#: modules/mono/editor/mono_bottom_panel.cpp msgid "View log" msgstr "" @@ -9319,6 +9348,13 @@ msgid "" "ParallaxLayer node only works when set as child of a ParallaxBackground node." msgstr "" +#: scene/2d/particles_2d.cpp +msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles2D node instead. You can use the \"Convert to " +"CPUParticles\" option for this purpose." +msgstr "" + #: scene/2d/particles_2d.cpp scene/3d/particles.cpp msgid "" "A material to process the particles is not assigned, so no behavior is " @@ -9474,6 +9510,13 @@ msgstr "" #: scene/3d/particles.cpp msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles node instead. You can use the \"Convert to CPUParticles" +"\" option for this purpose." +msgstr "" + +#: scene/3d/particles.cpp +msgid "" "Nothing is visible because meshes have not been assigned to draw passes." msgstr "" @@ -9504,21 +9547,6 @@ msgstr "" msgid "Path property must point to a valid Spatial node to work." msgstr "" -#: scene/3d/scenario_fx.cpp -msgid "WorldEnvironment needs an Environment resource." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " -"this environment's Background Mode to Canvas (for 2D scenes)." -msgstr "" - #: scene/3d/soft_body.cpp msgid "This body will be ignored until you set a mesh" msgstr "" @@ -9542,6 +9570,21 @@ msgid "" "it as a child of a VehicleBody." msgstr "" +#: scene/3d/world_environment.cpp +msgid "WorldEnvironment needs an Environment resource." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " +"this environment's Background Mode to Canvas (for 2D scenes)." +msgstr "" + #: scene/animation/animation_blend_tree.cpp msgid "On BlendTree node '%s', animation not found: '%s'" msgstr "" @@ -9587,11 +9630,19 @@ msgid "This node has been deprecated. Use AnimationTree instead." msgstr "" #: scene/gui/color_picker.cpp +msgid "Pick a color from the screen." +msgstr "" + +#: scene/gui/color_picker.cpp msgid "Raw Mode" msgstr "" #: scene/gui/color_picker.cpp -msgid "Add current color as a preset" +msgid "Switch between hexadecimal and code values." +msgstr "" + +#: scene/gui/color_picker.cpp +msgid "Add current color as a preset." msgstr "" #: scene/gui/dialogs.cpp @@ -9674,6 +9725,12 @@ msgstr "" msgid "Varyings can only be assigned in vertex function." msgstr "" +#~ msgid "Line:" +#~ msgstr "Reël:" + +#~ msgid "Col:" +#~ msgstr "Kol:" + #, fuzzy #~ msgid "Split already exists." #~ msgstr "AutoLaai '%s' bestaan reeds!" diff --git a/editor/translations/ar.po b/editor/translations/ar.po index 83a9c0b676..4870528b89 100644 --- a/editor/translations/ar.po +++ b/editor/translations/ar.po @@ -14,7 +14,7 @@ # omar anwar aglan <omar.aglan91@yahoo.com>, 2017-2018. # OWs Tetra <owstetra@gmail.com>, 2017. # Rached Noureddine <rached.noureddine@gmail.com>, 2018. -# Rex_sa <asd1234567890m@gmail.com>, 2017, 2018. +# Rex_sa <asd1234567890m@gmail.com>, 2017, 2018, 2019. # Wajdi Feki <wajdi.feki@gmail.com>, 2017. # Omar Aglan <omar.aglan91@yahoo.com>, 2018, 2019. # Codes Otaku <ilyas.gamerz@gmail.com>, 2018. @@ -22,12 +22,13 @@ # Mohamed El-Baz <albaz2000eg@gmail.com>, 2018. # عاصم شكر - Aasem shokr <aasemshokr@gmail.com>, 2018. # Mohammad Fares <mhdchehade@gmail.com>, 2018. +# NewFriskFan26 <newfriskfan26@gmail.com>, 2019. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2019-01-21 19:30+0000\n" -"Last-Translator: Omar Aglan <omar.aglan91@yahoo.com>\n" +"PO-Revision-Date: 2019-02-18 08:54+0000\n" +"Last-Translator: Rex_sa <asd1234567890m@gmail.com>\n" "Language-Team: Arabic <https://hosted.weblate.org/projects/godot-engine/" "godot/ar/>\n" "Language: ar\n" @@ -36,7 +37,7 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 " "&& n%100<=10 ? 3 : n%100>=11 ? 4 : 5;\n" -"X-Generator: Weblate 3.4-dev\n" +"X-Generator: Weblate 3.5-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -51,7 +52,7 @@ msgstr "لا يوجد ما يكÙÙŠ من البايتات من أجل ÙÙƒ Ø§Ù„Ø #: core/math/expression.cpp msgid "Invalid input %i (not passed) in expression" -msgstr "" +msgstr "Ù…ÙØ¯Ø®Ù„ غير ØµØ§Ù„Ø \"i%\" (لم يتم تمريره) ÙÙŠ السطر" #: core/math/expression.cpp msgid "self can't be used because instance is null (not passed)" @@ -141,11 +142,11 @@ msgstr "خط Ø§Ù„ØªØØ±ÙŠÙƒ ثلاثي الأبعاد" #: editor/animation_track_editor.cpp msgid "Call Method Track" -msgstr "" +msgstr "استدعاء أسلوب المسار" #: editor/animation_track_editor.cpp msgid "Bezier Curve Track" -msgstr "" +msgstr "مسار منØÙ†Ù‰ بيزيه" #: editor/animation_track_editor.cpp msgid "Audio Playback Track" @@ -186,7 +187,7 @@ msgstr "تمكين/إيقا٠هذا المسار." #: editor/animation_track_editor.cpp msgid "Update Mode (How this property is set)" -msgstr "" +msgstr "وضع Ø§Ù„ØªØØ¯ÙŠØ« (كي٠يتم تعيين هذه الخاصية)" #: editor/animation_track_editor.cpp #, fuzzy @@ -226,7 +227,7 @@ msgstr "المستقبل" #: editor/animation_track_editor.cpp msgid "Nearest" -msgstr "" +msgstr "أقرب" #: editor/animation_track_editor.cpp editor/plugins/curve_editor_plugin.cpp #: editor/property_editor.cpp @@ -235,7 +236,7 @@ msgstr "خطي" #: editor/animation_track_editor.cpp msgid "Cubic" -msgstr "" +msgstr "مكعب" #: editor/animation_track_editor.cpp msgid "Clamp Loop Interp" @@ -567,22 +568,13 @@ msgstr "إبعاد" msgid "Reset Zoom" msgstr "إرجاع التكبير" -#: editor/code_editor.cpp -msgid "Warnings:" +#: editor/code_editor.cpp modules/mono/editor/mono_bottom_panel.cpp +msgid "Warnings" msgstr "" #: editor/code_editor.cpp -#, fuzzy -msgid "Font Size:" -msgstr "ØØ¬Ù… الخطوط:" - -#: editor/code_editor.cpp -msgid "Line:" -msgstr "الخط:" - -#: editor/code_editor.cpp -msgid "Col:" -msgstr "العمود:" +msgid "Line and column numbers." +msgstr "" #: editor/connections_dialog.cpp msgid "Method in target Node must be specified!" @@ -890,8 +882,8 @@ msgstr "Ø¥Ù…Ø³Ø Ø§Ù„Ù…Ù„ÙØ§Øª Ø§Ù„Ù…ØØ¯Ø¯Ø©ØŸ" #: editor/dependency_editor.cpp editor/editor_audio_buses.cpp #: editor/editor_file_dialog.cpp editor/editor_node.cpp #: editor/filesystem_dock.cpp editor/plugins/item_list_editor_plugin.cpp -#: editor/project_export.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_dock.cpp +#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp +#: editor/project_settings_editor.cpp editor/scene_tree_dock.cpp msgid "Delete" msgstr "مسØ" @@ -1148,8 +1140,9 @@ msgid "Add Bus" msgstr "أض٠بيوس" #: editor/editor_audio_buses.cpp -msgid "Create a new Bus Layout." -msgstr "أنشئ نسق بيوس جديد." +#, fuzzy +msgid "Add a new Audio Bus to this layout." +msgstr "Ø¥ØÙظ نسق بيوس الصوت كـ..." #: editor/editor_audio_buses.cpp editor/editor_properties.cpp #: editor/plugins/animation_player_editor_plugin.cpp editor/property_editor.cpp @@ -1177,6 +1170,10 @@ msgstr "تØÙ…يل Ø§Ù„Ø¥ÙØªØ±Ø§Ø¶ÙŠ" msgid "Load the default Bus Layout." msgstr "تØÙ…يل نسق البيوس Ø§Ù„Ø¥ÙØªØ±Ø§Ø¶ÙŠ." +#: editor/editor_audio_buses.cpp +msgid "Create a new Bus Layout." +msgstr "أنشئ نسق بيوس جديد." + #: editor/editor_autoload_settings.cpp msgid "Invalid name." msgstr "اسم غير صالØ." @@ -2435,7 +2432,8 @@ msgid "Save & Restart" msgstr "ØÙظ Ùˆ خروج" #: editor/editor_node.cpp -msgid "Spins when the editor window repaints!" +#, fuzzy +msgid "Spins when the editor window redraws." msgstr "يدور ØÙŠÙ†Ù…ا Ù†Ø§ÙØ°Ø© Ø§Ù„Ù…ÙØ¹Ø¯Ù„ يتم إعادة دهانة!" #: editor/editor_node.cpp @@ -3524,25 +3522,6 @@ msgid "Create Polygon" msgstr "إنشاء بولي" #: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Edit Polygon" -msgstr "تعديل البولي" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Insert Point" -msgstr "إدخال نقطة" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Edit Polygon (Remove Point)" -msgstr "تعديل البولي (Ù…Ø³Ø Ø§Ù„Ù†Ù‚Ø·Ø©)" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Remove Polygon And Point" -msgstr "Ù…Ø³Ø Ø§Ù„Ø¨ÙˆÙ„ÙŠ والنقطة" - -#: editor/plugins/abstract_polygon_2d_editor.cpp #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #, fuzzy @@ -3567,6 +3546,25 @@ msgstr "" msgid "Erase points." msgstr "زر Ø§Ù„ÙØ£Ø±Ø© الأيمن: Ù…Ø³Ø Ø§Ù„Ù†Ù‚Ø·Ø©." +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Edit Polygon" +msgstr "تعديل البولي" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Insert Point" +msgstr "إدخال نقطة" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Edit Polygon (Remove Point)" +msgstr "تعديل البولي (Ù…Ø³Ø Ø§Ù„Ù†Ù‚Ø·Ø©)" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Remove Polygon And Point" +msgstr "Ù…Ø³Ø Ø§Ù„Ø¨ÙˆÙ„ÙŠ والنقطة" + #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #: editor/plugins/animation_player_editor_plugin.cpp @@ -4380,6 +4378,16 @@ msgid "Move CanvasItem" msgstr "تعديل العنصر القماشي" #: editor/plugins/canvas_item_editor_plugin.cpp +msgid "Presets for the anchors and margins values of a Control node." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp +msgid "" +"Children of containers have their anchors and margins values overridden by " +"their parent." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp msgid "Anchors only" msgstr "المرتكزات Ùقط" @@ -5296,6 +5304,12 @@ msgid "Create UV Map" msgstr "" #: editor/plugins/polygon_2d_editor_plugin.cpp +msgid "" +"Polygon 2D has internal vertices, so it can no longer be edited in the " +"viewport." +msgstr "" + +#: editor/plugins/polygon_2d_editor_plugin.cpp #, fuzzy msgid "Create Polygon & UV" msgstr "إنشاء بولي" @@ -6426,7 +6440,7 @@ msgid "Post" msgstr "" #: editor/plugins/spatial_editor_plugin.cpp -msgid "Name-less gizmo" +msgid "Nameless gizmo" msgstr "" #: editor/plugins/sprite_editor_plugin.cpp @@ -6507,8 +6521,14 @@ msgid "(empty)" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animations" -msgstr "" +#, fuzzy +msgid "Animations:" +msgstr "صورة Ù…ØªØØ±ÙƒØ©" + +#: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "New Animation" +msgstr "صورة Ù…ØªØØ±ÙƒØ©" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed (FPS):" @@ -6519,8 +6539,9 @@ msgid "Loop" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animation Frames" -msgstr "" +#, fuzzy +msgid "Animation Frames:" +msgstr "إسم Ø§Ù„ØØ±ÙƒØ©:" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Insert Empty (Before)" @@ -7346,6 +7367,19 @@ msgstr "" #: editor/project_manager.cpp msgid "" +"The following project settings file does not specify the version of Godot " +"through which it was created.\n" +"\n" +"%s\n" +"\n" +"If you proceed with opening it, it will be converted to Godot's current " +"configuration file format.\n" +"Warning: You will not be able to open the project with previous versions of " +"the engine anymore." +msgstr "" + +#: editor/project_manager.cpp +msgid "" "The following project settings file was generated by an older engine " "version, and needs to be converted for this version:\n" "\n" @@ -8857,10 +8891,6 @@ msgid "Build Project" msgstr "بناء المشروع" #: modules/mono/editor/mono_bottom_panel.cpp -msgid "Warnings" -msgstr "" - -#: modules/mono/editor/mono_bottom_panel.cpp #, fuzzy msgid "View log" msgstr "إظهار Ø§Ù„Ù…Ù„ÙØ§Øª" @@ -9501,6 +9531,13 @@ msgid "" "ParallaxLayer node only works when set as child of a ParallaxBackground node." msgstr "" +#: scene/2d/particles_2d.cpp +msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles2D node instead. You can use the \"Convert to " +"CPUParticles\" option for this purpose." +msgstr "" + #: scene/2d/particles_2d.cpp scene/3d/particles.cpp msgid "" "A material to process the particles is not assigned, so no behavior is " @@ -9656,6 +9693,13 @@ msgstr "" #: scene/3d/particles.cpp msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles node instead. You can use the \"Convert to CPUParticles" +"\" option for this purpose." +msgstr "" + +#: scene/3d/particles.cpp +msgid "" "Nothing is visible because meshes have not been assigned to draw passes." msgstr "" @@ -9686,21 +9730,6 @@ msgstr "" msgid "Path property must point to a valid Spatial node to work." msgstr "" -#: scene/3d/scenario_fx.cpp -msgid "WorldEnvironment needs an Environment resource." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " -"this environment's Background Mode to Canvas (for 2D scenes)." -msgstr "" - #: scene/3d/soft_body.cpp msgid "This body will be ignored until you set a mesh" msgstr "" @@ -9724,6 +9753,21 @@ msgid "" "it as a child of a VehicleBody." msgstr "" +#: scene/3d/world_environment.cpp +msgid "WorldEnvironment needs an Environment resource." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " +"this environment's Background Mode to Canvas (for 2D scenes)." +msgstr "" + #: scene/animation/animation_blend_tree.cpp msgid "On BlendTree node '%s', animation not found: '%s'" msgstr "" @@ -9770,11 +9814,20 @@ msgid "This node has been deprecated. Use AnimationTree instead." msgstr "" #: scene/gui/color_picker.cpp +msgid "Pick a color from the screen." +msgstr "" + +#: scene/gui/color_picker.cpp msgid "Raw Mode" msgstr "" #: scene/gui/color_picker.cpp -msgid "Add current color as a preset" +msgid "Switch between hexadecimal and code values." +msgstr "" + +#: scene/gui/color_picker.cpp +#, fuzzy +msgid "Add current color as a preset." msgstr "أض٠اللون Ø§Ù„ØØ§Ù„ÙŠ كإعداد مسبق" #: scene/gui/dialogs.cpp @@ -9860,6 +9913,16 @@ msgid "Varyings can only be assigned in vertex function." msgstr "" #, fuzzy +#~ msgid "Font Size:" +#~ msgstr "ØØ¬Ù… الخطوط:" + +#~ msgid "Line:" +#~ msgstr "الخط:" + +#~ msgid "Col:" +#~ msgstr "العمود:" + +#, fuzzy #~ msgid "Split already exists." #~ msgstr "التØÙ…يل التلقائي '%s' موجود اصلا!" diff --git a/editor/translations/bg.po b/editor/translations/bg.po index 02907898dd..cbab22b334 100644 --- a/editor/translations/bg.po +++ b/editor/translations/bg.po @@ -7,12 +7,13 @@ # Любомир ВаÑилев <lyubomirv@abv.bg>, 2018. # MaresPW <marespw206@gmail.com>, 2018. # PakoSt <kokotekilata@gmail.com>, 2018. +# Damyan Dichev <mwshock2@gmail.com>, 2019. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2018-12-13 14:38+0100\n" -"Last-Translator: PakoSt <kokotekilata@gmail.com>\n" +"PO-Revision-Date: 2019-02-13 07:10+0000\n" +"Last-Translator: Damyan Dichev <mwshock2@gmail.com>\n" "Language-Team: Bulgarian <https://hosted.weblate.org/projects/godot-engine/" "godot/bg/>\n" "Language: bg\n" @@ -20,7 +21,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Poedit 2.2\n" +"X-Generator: Weblate 3.5-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -45,11 +46,12 @@ msgstr "" #: core/math/expression.cpp msgid "Invalid operands to operator %s, %s and %s." -msgstr "" +msgstr "Ðевалидни операнди към оператор %s, %s и %s." #: core/math/expression.cpp +#, fuzzy msgid "Invalid index of type %s for base type %s" -msgstr "" +msgstr "Ðевалиден Ð¸Ð½Ð´ÐµÐºÑ Ð¾Ñ‚ тип %s за базов тип %s" #: core/math/expression.cpp msgid "Invalid named index '%s' for base type %s" @@ -552,22 +554,13 @@ msgstr "Отдалечи" msgid "Reset Zoom" msgstr "" -#: editor/code_editor.cpp -msgid "Warnings:" -msgstr "ПредупреждениÑ:" - -#: editor/code_editor.cpp -#, fuzzy -msgid "Font Size:" -msgstr "Изглед Отпред." - -#: editor/code_editor.cpp -msgid "Line:" -msgstr "Ред:" +#: editor/code_editor.cpp modules/mono/editor/mono_bottom_panel.cpp +msgid "Warnings" +msgstr "" #: editor/code_editor.cpp -msgid "Col:" -msgstr "Колона:" +msgid "Line and column numbers." +msgstr "" #: editor/connections_dialog.cpp msgid "Method in target Node must be specified!" @@ -863,8 +856,8 @@ msgstr "Изтрий избраните файлове?" #: editor/dependency_editor.cpp editor/editor_audio_buses.cpp #: editor/editor_file_dialog.cpp editor/editor_node.cpp #: editor/filesystem_dock.cpp editor/plugins/item_list_editor_plugin.cpp -#: editor/project_export.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_dock.cpp +#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp +#: editor/project_settings_editor.cpp editor/scene_tree_dock.cpp msgid "Delete" msgstr "Изтрий" @@ -1117,7 +1110,7 @@ msgid "Add Bus" msgstr "" #: editor/editor_audio_buses.cpp -msgid "Create a new Bus Layout." +msgid "Add a new Audio Bus to this layout." msgstr "" #: editor/editor_audio_buses.cpp editor/editor_properties.cpp @@ -1146,6 +1139,10 @@ msgstr "" msgid "Load the default Bus Layout." msgstr "" +#: editor/editor_audio_buses.cpp +msgid "Create a new Bus Layout." +msgstr "" + #: editor/editor_autoload_settings.cpp msgid "Invalid name." msgstr "" @@ -2351,7 +2348,7 @@ msgid "Save & Restart" msgstr "Запазване и повторно внаÑÑне" #: editor/editor_node.cpp -msgid "Spins when the editor window repaints!" +msgid "Spins when the editor window redraws." msgstr "" #: editor/editor_node.cpp @@ -3450,24 +3447,6 @@ msgid "Create Polygon" msgstr "Създаване на папка" #: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Edit Polygon" -msgstr "ПриÑтавки" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Insert Point" -msgstr "" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Edit Polygon (Remove Point)" -msgstr "" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Remove Polygon And Point" -msgstr "ПремеÑтване на Полигон" - -#: editor/plugins/abstract_polygon_2d_editor.cpp #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp msgid "Create points." @@ -3490,6 +3469,24 @@ msgstr "" msgid "Erase points." msgstr "Изтрий точки." +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Edit Polygon" +msgstr "ПриÑтавки" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Insert Point" +msgstr "" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Edit Polygon (Remove Point)" +msgstr "" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Remove Polygon And Point" +msgstr "ПремеÑтване на Полигон" + #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #: editor/plugins/animation_player_editor_plugin.cpp @@ -4294,6 +4291,16 @@ msgid "Move CanvasItem" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp +msgid "Presets for the anchors and margins values of a Control node." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp +msgid "" +"Children of containers have their anchors and margins values overridden by " +"their parent." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp msgid "Anchors only" msgstr "" @@ -5200,6 +5207,12 @@ msgid "Create UV Map" msgstr "" #: editor/plugins/polygon_2d_editor_plugin.cpp +msgid "" +"Polygon 2D has internal vertices, so it can no longer be edited in the " +"viewport." +msgstr "" + +#: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Create Polygon & UV" msgstr "" @@ -6313,7 +6326,7 @@ msgid "Post" msgstr "" #: editor/plugins/spatial_editor_plugin.cpp -msgid "Name-less gizmo" +msgid "Nameless gizmo" msgstr "" #: editor/plugins/sprite_editor_plugin.cpp @@ -6392,8 +6405,14 @@ msgid "(empty)" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animations" -msgstr "" +#, fuzzy +msgid "Animations:" +msgstr "Ðнимационни ИнÑтрументи" + +#: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "New Animation" +msgstr "Ðово Име на ÐнимациÑ:" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed (FPS):" @@ -6404,8 +6423,9 @@ msgid "Loop" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animation Frames" -msgstr "" +#, fuzzy +msgid "Animation Frames:" +msgstr "Ðово Име на ÐнимациÑ:" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Insert Empty (Before)" @@ -7233,6 +7253,19 @@ msgstr "" #: editor/project_manager.cpp msgid "" +"The following project settings file does not specify the version of Godot " +"through which it was created.\n" +"\n" +"%s\n" +"\n" +"If you proceed with opening it, it will be converted to Godot's current " +"configuration file format.\n" +"Warning: You will not be able to open the project with previous versions of " +"the engine anymore." +msgstr "" + +#: editor/project_manager.cpp +msgid "" "The following project settings file was generated by an older engine " "version, and needs to be converted for this version:\n" "\n" @@ -8768,10 +8801,6 @@ msgid "Build Project" msgstr "Проект" #: modules/mono/editor/mono_bottom_panel.cpp -msgid "Warnings" -msgstr "" - -#: modules/mono/editor/mono_bottom_panel.cpp #, fuzzy msgid "View log" msgstr "Преглед на файловете" @@ -9436,6 +9465,13 @@ msgid "" "ParallaxLayer node only works when set as child of a ParallaxBackground node." msgstr "ParallaxLayer работи Ñамо когато е наÑледник на ParallaxBackground." +#: scene/2d/particles_2d.cpp +msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles2D node instead. You can use the \"Convert to " +"CPUParticles\" option for this purpose." +msgstr "" + #: scene/2d/particles_2d.cpp scene/3d/particles.cpp msgid "" "A material to process the particles is not assigned, so no behavior is " @@ -9593,6 +9629,13 @@ msgstr "" #: scene/3d/particles.cpp msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles node instead. You can use the \"Convert to CPUParticles" +"\" option for this purpose." +msgstr "" + +#: scene/3d/particles.cpp +msgid "" "Nothing is visible because meshes have not been assigned to draw passes." msgstr "" @@ -9627,21 +9670,6 @@ msgstr "" "Параметърът 'Path' трÑбва да Ñочи към дейÑтвителен възел Particles2D, за да " "работи." -#: scene/3d/scenario_fx.cpp -msgid "WorldEnvironment needs an Environment resource." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " -"this environment's Background Mode to Canvas (for 2D scenes)." -msgstr "" - #: scene/3d/soft_body.cpp msgid "This body will be ignored until you set a mesh" msgstr "" @@ -9665,6 +9693,21 @@ msgid "" "it as a child of a VehicleBody." msgstr "" +#: scene/3d/world_environment.cpp +msgid "WorldEnvironment needs an Environment resource." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " +"this environment's Background Mode to Canvas (for 2D scenes)." +msgstr "" + #: scene/animation/animation_blend_tree.cpp msgid "On BlendTree node '%s', animation not found: '%s'" msgstr "" @@ -9706,11 +9749,19 @@ msgid "This node has been deprecated. Use AnimationTree instead." msgstr "" #: scene/gui/color_picker.cpp +msgid "Pick a color from the screen." +msgstr "" + +#: scene/gui/color_picker.cpp msgid "Raw Mode" msgstr "" #: scene/gui/color_picker.cpp -msgid "Add current color as a preset" +msgid "Switch between hexadecimal and code values." +msgstr "" + +#: scene/gui/color_picker.cpp +msgid "Add current color as a preset." msgstr "" #: scene/gui/dialogs.cpp @@ -9793,6 +9844,19 @@ msgstr "" msgid "Varyings can only be assigned in vertex function." msgstr "" +#~ msgid "Warnings:" +#~ msgstr "ПредупреждениÑ:" + +#, fuzzy +#~ msgid "Font Size:" +#~ msgstr "Изглед Отпред." + +#~ msgid "Line:" +#~ msgstr "Ред:" + +#~ msgid "Col:" +#~ msgstr "Колона:" + #, fuzzy #~ msgid "OrientedPathFollow only works when set as a child of a Path node." #~ msgstr "PathFollow2D работи Ñамо когато е наÑледник на Path2D." diff --git a/editor/translations/bn.po b/editor/translations/bn.po index fb4979b319..5d24e2b222 100644 --- a/editor/translations/bn.po +++ b/editor/translations/bn.po @@ -570,23 +570,14 @@ msgstr "সংকà§à¦šà¦¿à¦¤ করà§à¦¨ (জà§à¦®à§ আউট)" msgid "Reset Zoom" msgstr "সমà§à¦ªà§à¦°à¦¸à¦¾à¦°à¦¨/সংকোচন অপসারণ করà§à¦¨ (রিসেট জà§à¦®à§)" -#: editor/code_editor.cpp +#: editor/code_editor.cpp modules/mono/editor/mono_bottom_panel.cpp #, fuzzy -msgid "Warnings:" +msgid "Warnings" msgstr "সতরà§à¦•তা" #: editor/code_editor.cpp -#, fuzzy -msgid "Font Size:" -msgstr "উৎস ফনà§à¦Ÿà§‡à¦° আকার:" - -#: editor/code_editor.cpp -msgid "Line:" -msgstr "লাইন:" - -#: editor/code_editor.cpp -msgid "Col:" -msgstr "কলাম:" +msgid "Line and column numbers." +msgstr "" #: editor/connections_dialog.cpp msgid "Method in target Node must be specified!" @@ -900,8 +891,8 @@ msgstr "নিরà§à¦¬à¦¾à¦šà¦¿à¦¤ ফাইলসমূহ অপসারণ #: editor/dependency_editor.cpp editor/editor_audio_buses.cpp #: editor/editor_file_dialog.cpp editor/editor_node.cpp #: editor/filesystem_dock.cpp editor/plugins/item_list_editor_plugin.cpp -#: editor/project_export.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_dock.cpp +#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp +#: editor/project_settings_editor.cpp editor/scene_tree_dock.cpp msgid "Delete" msgstr "অপসারণ করà§à¦¨" @@ -1159,8 +1150,9 @@ msgid "Add Bus" msgstr "বাস যোগ করà§à¦¨" #: editor/editor_audio_buses.cpp -msgid "Create a new Bus Layout." -msgstr "নতà§à¦¨ বাস লেআউট তৈরি করà§à¦¨à¥¤" +#, fuzzy +msgid "Add a new Audio Bus to this layout." +msgstr "অডিও বাস লেআউট সেঠকরà§à¦¨..." #: editor/editor_audio_buses.cpp editor/editor_properties.cpp #: editor/plugins/animation_player_editor_plugin.cpp editor/property_editor.cpp @@ -1188,6 +1180,10 @@ msgstr "লোড ডিফলà§à¦Ÿ" msgid "Load the default Bus Layout." msgstr "ডিফলà§à¦Ÿ বাস লেআউট লোড করà§à¦¨à¥¤" +#: editor/editor_audio_buses.cpp +msgid "Create a new Bus Layout." +msgstr "নতà§à¦¨ বাস লেআউট তৈরি করà§à¦¨à¥¤" + #: editor/editor_autoload_settings.cpp msgid "Invalid name." msgstr "অগà§à¦°à¦¹à¦¨à¦¯à§‹à¦—à§à¦¯ নাম।" @@ -2501,7 +2497,8 @@ msgid "Save & Restart" msgstr "সংরকà§à¦·à¦£ à¦à¦¬à¦‚ পà§à¦¨-ইমà§à¦ªà§‹à¦°à§à¦Ÿ করà§à¦¨" #: editor/editor_node.cpp -msgid "Spins when the editor window repaints!" +#, fuzzy +msgid "Spins when the editor window redraws." msgstr "à¦à¦¡à¦¿à¦Ÿà¦°à§‡à¦° পà§à¦¨-অঙà§à¦•নে à¦à¦Ÿà¦¿ ঘূরà§à¦£à¦¨ করে!" #: editor/editor_node.cpp @@ -3669,26 +3666,6 @@ msgid "Create Polygon" msgstr "Poly তৈরি করà§à¦¨" #: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Edit Polygon" -msgstr "Poly সমà§à¦ªà¦¾à¦¦à¦¨ করà§à¦¨" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Insert Point" -msgstr "সনà§à¦¨à¦¿à¦¬à§‡à¦¶à¦¿à¦¤ হচà§à¦›à§‡" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Edit Polygon (Remove Point)" -msgstr "Poly সমà§à¦ªà¦¾à¦¦à¦¨ করà§à¦¨ (বিনà§à¦¦à§ অপসারণ করà§à¦¨)" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Remove Polygon And Point" -msgstr "পলি à¦à¦¬à¦‚ বিনà§à¦¦à§ অপসারণ করà§à¦¨" - -#: editor/plugins/abstract_polygon_2d_editor.cpp #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #, fuzzy @@ -3713,6 +3690,26 @@ msgstr "" msgid "Erase points." msgstr "মাউসের ডান বোতাম: বিনà§à¦¦à§ মà§à¦›à§‡ ফেলà§à¦¨à¥¤" +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Edit Polygon" +msgstr "Poly সমà§à¦ªà¦¾à¦¦à¦¨ করà§à¦¨" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Insert Point" +msgstr "সনà§à¦¨à¦¿à¦¬à§‡à¦¶à¦¿à¦¤ হচà§à¦›à§‡" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Edit Polygon (Remove Point)" +msgstr "Poly সমà§à¦ªà¦¾à¦¦à¦¨ করà§à¦¨ (বিনà§à¦¦à§ অপসারণ করà§à¦¨)" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Remove Polygon And Point" +msgstr "পলি à¦à¦¬à¦‚ বিনà§à¦¦à§ অপসারণ করà§à¦¨" + #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #: editor/plugins/animation_player_editor_plugin.cpp @@ -4544,6 +4541,16 @@ msgid "Move CanvasItem" msgstr "CanvasItem সমà§à¦ªà¦¾à¦¦à¦¨ করà§à¦¨" #: editor/plugins/canvas_item_editor_plugin.cpp +msgid "Presets for the anchors and margins values of a Control node." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp +msgid "" +"Children of containers have their anchors and margins values overridden by " +"their parent." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp #, fuzzy msgid "Anchors only" msgstr "অà§à¦¯à¦¾à¦‚কর" @@ -5503,6 +5510,12 @@ msgid "Create UV Map" msgstr "UV Map তৈরি করà§à¦¨" #: editor/plugins/polygon_2d_editor_plugin.cpp +msgid "" +"Polygon 2D has internal vertices, so it can no longer be edited in the " +"viewport." +msgstr "" + +#: editor/plugins/polygon_2d_editor_plugin.cpp #, fuzzy msgid "Create Polygon & UV" msgstr "Poly তৈরি করà§à¦¨" @@ -6677,7 +6690,7 @@ msgid "Post" msgstr "পরবরà§à¦¤à§€ (Post)" #: editor/plugins/spatial_editor_plugin.cpp -msgid "Name-less gizmo" +msgid "Nameless gizmo" msgstr "" #: editor/plugins/sprite_editor_plugin.cpp @@ -6760,10 +6773,16 @@ msgid "(empty)" msgstr "(খালি/শূনà§à¦¯)" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animations" +#, fuzzy +msgid "Animations:" msgstr "অà§à¦¯à¦¾à¦¨à¦¿à¦®à§‡à¦¶à¦¨à¦¸à¦®à§‚হ" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "New Animation" +msgstr "অà§à¦¯à¦¾à¦¨à¦¿à¦®à§‡à¦¶à¦¨" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed (FPS):" msgstr "গতি (FPS):" @@ -6772,7 +6791,8 @@ msgid "Loop" msgstr "লà§à¦ª" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animation Frames" +#, fuzzy +msgid "Animation Frames:" msgstr "অà§à¦¯à¦¾à¦¨à¦¿à¦®à§‡à¦¶à¦¨à§‡à¦° ফà§à¦°à§‡à¦®à¦¸à¦®à§‚হ" #: editor/plugins/sprite_frames_editor_plugin.cpp @@ -7645,6 +7665,19 @@ msgstr "à¦à¦•ধিক পà§à¦°à¦•লà§à¦ª খোলায় আপনি সৠ#: editor/project_manager.cpp msgid "" +"The following project settings file does not specify the version of Godot " +"through which it was created.\n" +"\n" +"%s\n" +"\n" +"If you proceed with opening it, it will be converted to Godot's current " +"configuration file format.\n" +"Warning: You will not be able to open the project with previous versions of " +"the engine anymore." +msgstr "" + +#: editor/project_manager.cpp +msgid "" "The following project settings file was generated by an older engine " "version, and needs to be converted for this version:\n" "\n" @@ -9261,11 +9294,6 @@ msgstr "নতà§à¦¨ পà§à¦°à¦•লà§à¦ª" #: modules/mono/editor/mono_bottom_panel.cpp #, fuzzy -msgid "Warnings" -msgstr "সতরà§à¦•তা" - -#: modules/mono/editor/mono_bottom_panel.cpp -#, fuzzy msgid "View log" msgstr "ফাইল" @@ -9966,6 +9994,13 @@ msgid "" msgstr "" "ParallaxLayer à¦à¦•মাতà§à¦° ParallaxBackground à¦à¦° অংশ হিসেবে নিরà§à¦§à¦¾à¦°à¦¨ করলেই কাজ করে।" +#: scene/2d/particles_2d.cpp +msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles2D node instead. You can use the \"Convert to " +"CPUParticles\" option for this purpose." +msgstr "" + #: scene/2d/particles_2d.cpp scene/3d/particles.cpp msgid "" "A material to process the particles is not assigned, so no behavior is " @@ -10139,6 +10174,13 @@ msgstr "" #: scene/3d/particles.cpp msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles node instead. You can use the \"Convert to CPUParticles" +"\" option for this purpose." +msgstr "" + +#: scene/3d/particles.cpp +msgid "" "Nothing is visible because meshes have not been assigned to draw passes." msgstr "" @@ -10170,23 +10212,6 @@ msgstr "" msgid "Path property must point to a valid Spatial node to work." msgstr "Path à¦à¦° দিক অবশà§à¦¯à¦‡ à¦à¦•টি কারà§à¦¯à¦•র Spatial নোডের à¦à¦° দিকে নিরà§à¦¦à§‡à¦¶ করাতে হবে।" -#: scene/3d/scenario_fx.cpp -msgid "WorldEnvironment needs an Environment resource." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." -msgstr "" -"পà§à¦°à¦¤à¦¿ দৃশà§à¦¯à§‡ (অথবা ইনà§à¦¸à¦Ÿà§à¦¯à¦¾à¦¨à§à¦¸à¦¡ দৃশà§à¦¯à§‡à¦° সমà§à¦®à§‡à¦²à¦¨à§‡) সরà§à¦¬à§‹à¦šà§à¦š à¦à¦•টি দৃশà§à¦¯à¦®à¦¾à¦¨ WorldEnvironment " -"সমà§à¦à¦¬à¥¤" - -#: scene/3d/scenario_fx.cpp -msgid "" -"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " -"this environment's Background Mode to Canvas (for 2D scenes)." -msgstr "" - #: scene/3d/soft_body.cpp msgid "This body will be ignored until you set a mesh" msgstr "" @@ -10212,6 +10237,23 @@ msgid "" "it as a child of a VehicleBody." msgstr "" +#: scene/3d/world_environment.cpp +msgid "WorldEnvironment needs an Environment resource." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." +msgstr "" +"পà§à¦°à¦¤à¦¿ দৃশà§à¦¯à§‡ (অথবা ইনà§à¦¸à¦Ÿà§à¦¯à¦¾à¦¨à§à¦¸à¦¡ দৃশà§à¦¯à§‡à¦° সমà§à¦®à§‡à¦²à¦¨à§‡) সরà§à¦¬à§‹à¦šà§à¦š à¦à¦•টি দৃশà§à¦¯à¦®à¦¾à¦¨ WorldEnvironment " +"সমà§à¦à¦¬à¥¤" + +#: scene/3d/world_environment.cpp +msgid "" +"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " +"this environment's Background Mode to Canvas (for 2D scenes)." +msgstr "" + #: scene/animation/animation_blend_tree.cpp msgid "On BlendTree node '%s', animation not found: '%s'" msgstr "" @@ -10259,12 +10301,20 @@ msgid "This node has been deprecated. Use AnimationTree instead." msgstr "" #: scene/gui/color_picker.cpp +msgid "Pick a color from the screen." +msgstr "" + +#: scene/gui/color_picker.cpp #, fuzzy msgid "Raw Mode" msgstr "পà§à¦¯à¦¾à¦¨ মোড" #: scene/gui/color_picker.cpp -msgid "Add current color as a preset" +msgid "Switch between hexadecimal and code values." +msgstr "" + +#: scene/gui/color_picker.cpp +msgid "Add current color as a preset." msgstr "" #: scene/gui/dialogs.cpp @@ -10357,6 +10407,20 @@ msgid "Varyings can only be assigned in vertex function." msgstr "" #, fuzzy +#~ msgid "Warnings:" +#~ msgstr "সতরà§à¦•তা" + +#, fuzzy +#~ msgid "Font Size:" +#~ msgstr "উৎস ফনà§à¦Ÿà§‡à¦° আকার:" + +#~ msgid "Line:" +#~ msgstr "লাইন:" + +#~ msgid "Col:" +#~ msgstr "কলাম:" + +#, fuzzy #~ msgid "OrientedPathFollow only works when set as a child of a Path node." #~ msgstr "PathFollow2D à¦à¦•মাতà§à¦° Path2D à¦à¦° অংশ হিসেবে নিরà§à¦§à¦¾à¦°à¦¨ করালেই কাজ করে।" diff --git a/editor/translations/ca.po b/editor/translations/ca.po index 156368509a..d43dae0f8e 100644 --- a/editor/translations/ca.po +++ b/editor/translations/ca.po @@ -547,22 +547,13 @@ msgstr "Allunya" msgid "Reset Zoom" msgstr "Reinicia el Zoom" -#: editor/code_editor.cpp -msgid "Warnings:" -msgstr "Avisos:" - -#: editor/code_editor.cpp -#, fuzzy -msgid "Font Size:" -msgstr "Mida de la lletra:" - -#: editor/code_editor.cpp -msgid "Line:" -msgstr "LÃnia:" +#: editor/code_editor.cpp modules/mono/editor/mono_bottom_panel.cpp +msgid "Warnings" +msgstr "Avisos" #: editor/code_editor.cpp -msgid "Col:" -msgstr "Col:" +msgid "Line and column numbers." +msgstr "" #: editor/connections_dialog.cpp msgid "Method in target Node must be specified!" @@ -866,8 +857,8 @@ msgstr "Voleu Esborrar els fitxers seleccionats?" #: editor/dependency_editor.cpp editor/editor_audio_buses.cpp #: editor/editor_file_dialog.cpp editor/editor_node.cpp #: editor/filesystem_dock.cpp editor/plugins/item_list_editor_plugin.cpp -#: editor/project_export.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_dock.cpp +#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp +#: editor/project_settings_editor.cpp editor/scene_tree_dock.cpp msgid "Delete" msgstr "Esborra" @@ -1124,8 +1115,9 @@ msgid "Add Bus" msgstr "Afegeix Bus" #: editor/editor_audio_buses.cpp -msgid "Create a new Bus Layout." -msgstr "Crea un nou Disseny de Bus." +#, fuzzy +msgid "Add a new Audio Bus to this layout." +msgstr "Anomena i Desa el Disseny del Bus d'Àudio..." #: editor/editor_audio_buses.cpp editor/editor_properties.cpp #: editor/plugins/animation_player_editor_plugin.cpp editor/property_editor.cpp @@ -1153,6 +1145,10 @@ msgstr "Carrega Valors predeterminats" msgid "Load the default Bus Layout." msgstr "Carrega el disseny del Bus predeterminat." +#: editor/editor_audio_buses.cpp +msgid "Create a new Bus Layout." +msgstr "Crea un nou Disseny de Bus." + #: editor/editor_autoload_settings.cpp msgid "Invalid name." msgstr "Nom no và lid." @@ -2429,7 +2425,8 @@ msgid "Save & Restart" msgstr "Desa i Reinicia" #: editor/editor_node.cpp -msgid "Spins when the editor window repaints!" +#, fuzzy +msgid "Spins when the editor window redraws." msgstr "Gira i Gira mentre l'editor es repinta!" #: editor/editor_node.cpp @@ -3492,25 +3489,6 @@ msgid "Create Polygon" msgstr "Crea PolÃgon" #: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Edit Polygon" -msgstr "Edita PolÃgon" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Insert Point" -msgstr "Insereix un Punt" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Edit Polygon (Remove Point)" -msgstr "Edita el PolÃgon (Elimina un Punt)" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Remove Polygon And Point" -msgstr "Elimina el PolÃgon i el Punt" - -#: editor/plugins/abstract_polygon_2d_editor.cpp #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp msgid "Create points." @@ -3533,6 +3511,25 @@ msgstr "" msgid "Erase points." msgstr "Elimina un Punt." +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Edit Polygon" +msgstr "Edita PolÃgon" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Insert Point" +msgstr "Insereix un Punt" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Edit Polygon (Remove Point)" +msgstr "Edita el PolÃgon (Elimina un Punt)" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Remove Polygon And Point" +msgstr "Elimina el PolÃgon i el Punt" + #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #: editor/plugins/animation_player_editor_plugin.cpp @@ -4356,6 +4353,16 @@ msgid "Move CanvasItem" msgstr "Modifica el elementCanvas" #: editor/plugins/canvas_item_editor_plugin.cpp +msgid "Presets for the anchors and margins values of a Control node." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp +msgid "" +"Children of containers have their anchors and margins values overridden by " +"their parent." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp msgid "Anchors only" msgstr "Només Ancoratges" @@ -5273,6 +5280,12 @@ msgid "Create UV Map" msgstr "Crea un Mapa UV" #: editor/plugins/polygon_2d_editor_plugin.cpp +msgid "" +"Polygon 2D has internal vertices, so it can no longer be edited in the " +"viewport." +msgstr "" + +#: editor/plugins/polygon_2d_editor_plugin.cpp #, fuzzy msgid "Create Polygon & UV" msgstr "Crea PolÃgon" @@ -6414,7 +6427,7 @@ msgid "Post" msgstr "Post" #: editor/plugins/spatial_editor_plugin.cpp -msgid "Name-less gizmo" +msgid "Nameless gizmo" msgstr "" #: editor/plugins/sprite_editor_plugin.cpp @@ -6496,10 +6509,16 @@ msgid "(empty)" msgstr "(buit)" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animations" +#, fuzzy +msgid "Animations:" msgstr "Animacions" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "New Animation" +msgstr "Animació" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed (FPS):" msgstr "Velocitat (FPS):" @@ -6508,7 +6527,8 @@ msgid "Loop" msgstr "Bucle" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animation Frames" +#, fuzzy +msgid "Animation Frames:" msgstr "Fotogrames d'Animació" #: editor/plugins/sprite_frames_editor_plugin.cpp @@ -7350,6 +7370,19 @@ msgstr "Esteu segur que voleu obrir més d'un projecte de cop?" #: editor/project_manager.cpp msgid "" +"The following project settings file does not specify the version of Godot " +"through which it was created.\n" +"\n" +"%s\n" +"\n" +"If you proceed with opening it, it will be converted to Godot's current " +"configuration file format.\n" +"Warning: You will not be able to open the project with previous versions of " +"the engine anymore." +msgstr "" + +#: editor/project_manager.cpp +msgid "" "The following project settings file was generated by an older engine " "version, and needs to be converted for this version:\n" "\n" @@ -8908,10 +8941,6 @@ msgid "Build Project" msgstr "Munta el Projecte" #: modules/mono/editor/mono_bottom_panel.cpp -msgid "Warnings" -msgstr "Avisos" - -#: modules/mono/editor/mono_bottom_panel.cpp msgid "View log" msgstr "Mostra el Registre" @@ -9593,6 +9622,13 @@ msgstr "" "Un node ParallaxLayer només funciona quan s'estableix com a fill d'un node " "ParallaxBackground." +#: scene/2d/particles_2d.cpp +msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles2D node instead. You can use the \"Convert to " +"CPUParticles\" option for this purpose." +msgstr "" + #: scene/2d/particles_2d.cpp scene/3d/particles.cpp msgid "" "A material to process the particles is not assigned, so no behavior is " @@ -9776,6 +9812,13 @@ msgstr "" #: scene/3d/particles.cpp msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles node instead. You can use the \"Convert to CPUParticles" +"\" option for this purpose." +msgstr "" + +#: scene/3d/particles.cpp +msgid "" "Nothing is visible because meshes have not been assigned to draw passes." msgstr "Res és visible perquè no s'ha assignat cap Malla a cap pas de Dibuix." @@ -9811,25 +9854,6 @@ msgstr "" msgid "Path property must point to a valid Spatial node to work." msgstr "Cal que la propietat Camà assenyali cap a un node Spatial và lid." -#: scene/3d/scenario_fx.cpp -msgid "WorldEnvironment needs an Environment resource." -msgstr "WorldEnvironment necessita un recurs Ambiental." - -#: scene/3d/scenario_fx.cpp -msgid "" -"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." -msgstr "" -"Només es permet un sol WorldEnvironment per escena ( o conjunt d'escenes " -"instanciades)." - -#: scene/3d/scenario_fx.cpp -msgid "" -"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " -"this environment's Background Mode to Canvas (for 2D scenes)." -msgstr "" -"Aquest WorldEnvironment s'ignora. Afegiu una cà mera (per a escenes 3D) o " -"configureu el Background Mode a Canvas (per a escenes 2D)." - #: scene/3d/soft_body.cpp msgid "This body will be ignored until you set a mesh" msgstr "" @@ -9862,6 +9886,25 @@ msgstr "" "RigidBody(Carà cter o RÃgid). \n" "Modifica la mida de les Formes de Col·lisió Filles." +#: scene/3d/world_environment.cpp +msgid "WorldEnvironment needs an Environment resource." +msgstr "WorldEnvironment necessita un recurs Ambiental." + +#: scene/3d/world_environment.cpp +msgid "" +"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." +msgstr "" +"Només es permet un sol WorldEnvironment per escena ( o conjunt d'escenes " +"instanciades)." + +#: scene/3d/world_environment.cpp +msgid "" +"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " +"this environment's Background Mode to Canvas (for 2D scenes)." +msgstr "" +"Aquest WorldEnvironment s'ignora. Afegiu una cà mera (per a escenes 3D) o " +"configureu el Background Mode a Canvas (per a escenes 2D)." + #: scene/animation/animation_blend_tree.cpp msgid "On BlendTree node '%s', animation not found: '%s'" msgstr "" @@ -9909,11 +9952,20 @@ msgid "This node has been deprecated. Use AnimationTree instead." msgstr "" #: scene/gui/color_picker.cpp +msgid "Pick a color from the screen." +msgstr "" + +#: scene/gui/color_picker.cpp msgid "Raw Mode" msgstr "Mode Cru" #: scene/gui/color_picker.cpp -msgid "Add current color as a preset" +msgid "Switch between hexadecimal and code values." +msgstr "" + +#: scene/gui/color_picker.cpp +#, fuzzy +msgid "Add current color as a preset." msgstr "Afegeix el Color actual com a predeterminat" #: scene/gui/dialogs.cpp @@ -10010,6 +10062,19 @@ msgstr "" msgid "Varyings can only be assigned in vertex function." msgstr "" +#~ msgid "Warnings:" +#~ msgstr "Avisos:" + +#, fuzzy +#~ msgid "Font Size:" +#~ msgstr "Mida de la lletra:" + +#~ msgid "Line:" +#~ msgstr "LÃnia:" + +#~ msgid "Col:" +#~ msgstr "Col:" + #, fuzzy #~ msgid "OrientedPathFollow only works when set as a child of a Path node." #~ msgstr "" diff --git a/editor/translations/cs.po b/editor/translations/cs.po index aa82d935de..b987e1d8ef 100644 --- a/editor/translations/cs.po +++ b/editor/translations/cs.po @@ -5,7 +5,7 @@ # Fadex <vitekpaulik@gmail.com>, 2017. # Jan 'spl!te' KondelÃk <j.kondelik@centrum.cz>, 2016, 2018. # Jiri Hysek <contact@jirihysek.com>, 2017. -# Josef KuchaÅ™ <josef.kuchar267@gmail.com>, 2018. +# Josef KuchaÅ™ <josef.kuchar267@gmail.com>, 2018, 2019. # LudÄ›k Novotný <gladosicek@gmail.com>, 2016, 2018. # Martin Novák <maidx@seznam.cz>, 2017. # zxey <r.hozak@seznam.cz>, 2018. @@ -14,8 +14,8 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2018-12-13 14:38+0100\n" -"Last-Translator: VojtÄ›ch Å amla <auzkok@seznam.cz>\n" +"PO-Revision-Date: 2019-02-10 12:01+0000\n" +"Last-Translator: Josef KuchaÅ™ <josef.kuchar267@gmail.com>\n" "Language-Team: Czech <https://hosted.weblate.org/projects/godot-engine/godot/" "cs/>\n" "Language: cs\n" @@ -23,7 +23,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" -"X-Generator: Poedit 2.2\n" +"X-Generator: Weblate 3.5-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -39,7 +39,7 @@ msgstr "Nedostatek bytů pro dekódovánà bytů, nebo Å¡patný formát." #: core/math/expression.cpp msgid "Invalid input %i (not passed) in expression" -msgstr "" +msgstr "Neplatný vstup %i (neproÅ¡el) ve výrazu" #: core/math/expression.cpp msgid "self can't be used because instance is null (not passed)" @@ -73,7 +73,7 @@ msgstr "Uvolnit" #: editor/animation_bezier_editor.cpp msgid "Balanced" -msgstr "" +msgstr "Vyvážený" #: editor/animation_bezier_editor.cpp #, fuzzy @@ -304,7 +304,7 @@ msgstr "" #: editor/animation_track_editor.cpp msgid "Animation tracks can only point to AnimationPlayer nodes." -msgstr "Stopa animae může odkazovat pouze na uzly AnimationPlayer." +msgstr "Stopa animace může odkazovat pouze na uzly AnimationPlayer." #: editor/animation_track_editor.cpp msgid "An animation player can't animate itself, only other players." @@ -550,22 +550,13 @@ msgstr "Oddálit" msgid "Reset Zoom" msgstr "Obnovit původnà pÅ™iblÞenÃ" -#: editor/code_editor.cpp -msgid "Warnings:" -msgstr "VarovánÃ:" - -#: editor/code_editor.cpp -#, fuzzy -msgid "Font Size:" -msgstr "Pohled zepÅ™edu" - -#: editor/code_editor.cpp -msgid "Line:" -msgstr "Řádek:" +#: editor/code_editor.cpp modules/mono/editor/mono_bottom_panel.cpp +msgid "Warnings" +msgstr "VarovánÃ" #: editor/code_editor.cpp -msgid "Col:" -msgstr "Sloupec:" +msgid "Line and column numbers." +msgstr "" #: editor/connections_dialog.cpp msgid "Method in target Node must be specified!" @@ -869,8 +860,8 @@ msgstr "Odstranit vybrané soubory?" #: editor/dependency_editor.cpp editor/editor_audio_buses.cpp #: editor/editor_file_dialog.cpp editor/editor_node.cpp #: editor/filesystem_dock.cpp editor/plugins/item_list_editor_plugin.cpp -#: editor/project_export.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_dock.cpp +#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp +#: editor/project_settings_editor.cpp editor/scene_tree_dock.cpp msgid "Delete" msgstr "Odstranit" @@ -1127,8 +1118,9 @@ msgid "Add Bus" msgstr "PÅ™idat bus" #: editor/editor_audio_buses.cpp -msgid "Create a new Bus Layout." -msgstr "" +#, fuzzy +msgid "Add a new Audio Bus to this layout." +msgstr "Uložit rozloženà Audio Busu jako..." #: editor/editor_audio_buses.cpp editor/editor_properties.cpp #: editor/plugins/animation_player_editor_plugin.cpp editor/property_editor.cpp @@ -1156,6 +1148,10 @@ msgstr "NaÄÃst výchozÃ" msgid "Load the default Bus Layout." msgstr "" +#: editor/editor_audio_buses.cpp +msgid "Create a new Bus Layout." +msgstr "" + #: editor/editor_autoload_settings.cpp msgid "Invalid name." msgstr "Neplatný název." @@ -1457,7 +1453,7 @@ msgstr "(Re)Importovánà assetů" #: editor/editor_help.cpp editor/plugins/spatial_editor_plugin.cpp msgid "Top" -msgstr "" +msgstr "HornÃ" #: editor/editor_help.cpp msgid "Class:" @@ -1629,7 +1625,7 @@ msgstr "Nastavit" #: editor/editor_inspector.cpp msgid "Set Multiple:" -msgstr "" +msgstr "Nastavit vÃce:" #: editor/editor_log.cpp msgid "Output:" @@ -2389,7 +2385,8 @@ msgid "Save & Restart" msgstr "Uložit a restartovat" #: editor/editor_node.cpp -msgid "Spins when the editor window repaints!" +#, fuzzy +msgid "Spins when the editor window redraws." msgstr "ToÄà se, když se okno pÅ™ekresluje!" #: editor/editor_node.cpp @@ -3447,25 +3444,6 @@ msgid "Create Polygon" msgstr "VytvoÅ™it polygon" #: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Edit Polygon" -msgstr "Editovat polygon" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Insert Point" -msgstr "Vložit polygon" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Edit Polygon (Remove Point)" -msgstr "Upravit polygon (Odstranit bod)" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Remove Polygon And Point" -msgstr "Odstranit polygon a bod" - -#: editor/plugins/abstract_polygon_2d_editor.cpp #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp msgid "Create points." @@ -3488,6 +3466,25 @@ msgstr "" msgid "Erase points." msgstr "Vymazat body." +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Edit Polygon" +msgstr "Editovat polygon" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Insert Point" +msgstr "Vložit polygon" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Edit Polygon (Remove Point)" +msgstr "Upravit polygon (Odstranit bod)" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Remove Polygon And Point" +msgstr "Odstranit polygon a bod" + #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #: editor/plugins/animation_player_editor_plugin.cpp @@ -4277,6 +4274,16 @@ msgid "Move CanvasItem" msgstr "PÅ™emÃstit CanvasItem" #: editor/plugins/canvas_item_editor_plugin.cpp +msgid "Presets for the anchors and margins values of a Control node." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp +msgid "" +"Children of containers have their anchors and margins values overridden by " +"their parent." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp msgid "Anchors only" msgstr "Pouze kotvy" @@ -5189,6 +5196,12 @@ msgid "Create UV Map" msgstr "VytvoÅ™it UV mapu" #: editor/plugins/polygon_2d_editor_plugin.cpp +msgid "" +"Polygon 2D has internal vertices, so it can no longer be edited in the " +"viewport." +msgstr "" + +#: editor/plugins/polygon_2d_editor_plugin.cpp #, fuzzy msgid "Create Polygon & UV" msgstr "VytvoÅ™it Poly3D" @@ -6299,7 +6312,7 @@ msgid "Post" msgstr "Po" #: editor/plugins/spatial_editor_plugin.cpp -msgid "Name-less gizmo" +msgid "Nameless gizmo" msgstr "" #: editor/plugins/sprite_editor_plugin.cpp @@ -6375,7 +6388,13 @@ msgid "(empty)" msgstr "(prázdný)" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animations" +#, fuzzy +msgid "Animations:" +msgstr "Animace" + +#: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "New Animation" msgstr "Animace" #: editor/plugins/sprite_frames_editor_plugin.cpp @@ -6387,7 +6406,8 @@ msgid "Loop" msgstr "SmyÄka" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animation Frames" +#, fuzzy +msgid "Animation Frames:" msgstr "SnÃmky animace" #: editor/plugins/sprite_frames_editor_plugin.cpp @@ -7206,6 +7226,19 @@ msgstr "Jste si jisti, že chcete otevÅ™it vÃce než jeden projekt?" #: editor/project_manager.cpp msgid "" +"The following project settings file does not specify the version of Godot " +"through which it was created.\n" +"\n" +"%s\n" +"\n" +"If you proceed with opening it, it will be converted to Godot's current " +"configuration file format.\n" +"Warning: You will not be able to open the project with previous versions of " +"the engine anymore." +msgstr "" + +#: editor/project_manager.cpp +msgid "" "The following project settings file was generated by an older engine " "version, and needs to be converted for this version:\n" "\n" @@ -8727,10 +8760,6 @@ msgid "Build Project" msgstr "Sestavit projekt" #: modules/mono/editor/mono_bottom_panel.cpp -msgid "Warnings" -msgstr "VarovánÃ" - -#: modules/mono/editor/mono_bottom_panel.cpp #, fuzzy msgid "View log" msgstr "Zobrazit soubory" @@ -9407,6 +9436,13 @@ msgid "" msgstr "" "Uzel ParallaxLayer funguje pouze když je dÃtÄ›tem uzlu ParallaxBackground." +#: scene/2d/particles_2d.cpp +msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles2D node instead. You can use the \"Convert to " +"CPUParticles\" option for this purpose." +msgstr "" + #: scene/2d/particles_2d.cpp scene/3d/particles.cpp msgid "" "A material to process the particles is not assigned, so no behavior is " @@ -9581,6 +9617,13 @@ msgstr "" #: scene/3d/particles.cpp msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles node instead. You can use the \"Convert to CPUParticles" +"\" option for this purpose." +msgstr "" + +#: scene/3d/particles.cpp +msgid "" "Nothing is visible because meshes have not been assigned to draw passes." msgstr "" @@ -9614,23 +9657,6 @@ msgstr "" "Aby ParticleAttractor2D fungoval, musà vlastnost path ukazovat na platný " "uzel Particles2D." -#: scene/3d/scenario_fx.cpp -msgid "WorldEnvironment needs an Environment resource." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." -msgstr "" -"Na každou scénu (nebo skupinu instancovaných scén) je povolen pouze jeden " -"WorldEnvironment." - -#: scene/3d/scenario_fx.cpp -msgid "" -"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " -"this environment's Background Mode to Canvas (for 2D scenes)." -msgstr "" - #: scene/3d/soft_body.cpp msgid "This body will be ignored until you set a mesh" msgstr "" @@ -9660,6 +9686,23 @@ msgstr "" "VehicleWheel sloužà jako systém kol pro VehicleBody. Použijte ho prosÃm jako " "potomka VehicleBody." +#: scene/3d/world_environment.cpp +msgid "WorldEnvironment needs an Environment resource." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." +msgstr "" +"Na každou scénu (nebo skupinu instancovaných scén) je povolen pouze jeden " +"WorldEnvironment." + +#: scene/3d/world_environment.cpp +msgid "" +"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " +"this environment's Background Mode to Canvas (for 2D scenes)." +msgstr "" + #: scene/animation/animation_blend_tree.cpp msgid "On BlendTree node '%s', animation not found: '%s'" msgstr "" @@ -9704,11 +9747,20 @@ msgid "This node has been deprecated. Use AnimationTree instead." msgstr "" #: scene/gui/color_picker.cpp +msgid "Pick a color from the screen." +msgstr "" + +#: scene/gui/color_picker.cpp msgid "Raw Mode" msgstr "RAW mód" #: scene/gui/color_picker.cpp -msgid "Add current color as a preset" +msgid "Switch between hexadecimal and code values." +msgstr "" + +#: scene/gui/color_picker.cpp +#, fuzzy +msgid "Add current color as a preset." msgstr "PÅ™idat aktuálnà barvu jako pÅ™edvolbu" #: scene/gui/dialogs.cpp @@ -9801,6 +9853,19 @@ msgstr "" msgid "Varyings can only be assigned in vertex function." msgstr "" +#~ msgid "Warnings:" +#~ msgstr "VarovánÃ:" + +#, fuzzy +#~ msgid "Font Size:" +#~ msgstr "Pohled zepÅ™edu" + +#~ msgid "Line:" +#~ msgstr "Řádek:" + +#~ msgid "Col:" +#~ msgstr "Sloupec:" + #~ msgid "OrientedPathFollow only works when set as a child of a Path node." #~ msgstr "OrientedPathFollow funguje pouze když je dÃtÄ›tem uzlu Path." diff --git a/editor/translations/da.po b/editor/translations/da.po index 6c6f3152db..41e00e3cbf 100644 --- a/editor/translations/da.po +++ b/editor/translations/da.po @@ -548,21 +548,13 @@ msgstr "Zoom Ud" msgid "Reset Zoom" msgstr "Nulstil Zoom" -#: editor/code_editor.cpp -msgid "Warnings:" -msgstr "Advarsler:" - -#: editor/code_editor.cpp -msgid "Font Size:" -msgstr "Skrifttype Størrelse:" - -#: editor/code_editor.cpp -msgid "Line:" -msgstr "Linje:" +#: editor/code_editor.cpp modules/mono/editor/mono_bottom_panel.cpp +msgid "Warnings" +msgstr "" #: editor/code_editor.cpp -msgid "Col:" -msgstr "Kol:" +msgid "Line and column numbers." +msgstr "" #: editor/connections_dialog.cpp msgid "Method in target Node must be specified!" @@ -864,8 +856,8 @@ msgstr "Slet markerede filer?" #: editor/dependency_editor.cpp editor/editor_audio_buses.cpp #: editor/editor_file_dialog.cpp editor/editor_node.cpp #: editor/filesystem_dock.cpp editor/plugins/item_list_editor_plugin.cpp -#: editor/project_export.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_dock.cpp +#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp +#: editor/project_settings_editor.cpp editor/scene_tree_dock.cpp msgid "Delete" msgstr "Slet" @@ -1121,8 +1113,9 @@ msgid "Add Bus" msgstr "Tilføj Bus" #: editor/editor_audio_buses.cpp -msgid "Create a new Bus Layout." -msgstr "Opret et nyt Bus Layout." +#, fuzzy +msgid "Add a new Audio Bus to this layout." +msgstr "Gem Audio Bus Layout Som..." #: editor/editor_audio_buses.cpp editor/editor_properties.cpp #: editor/plugins/animation_player_editor_plugin.cpp editor/property_editor.cpp @@ -1150,6 +1143,10 @@ msgstr "Indlæs Default" msgid "Load the default Bus Layout." msgstr "Indlæs standard Bus Layout." +#: editor/editor_audio_buses.cpp +msgid "Create a new Bus Layout." +msgstr "Opret et nyt Bus Layout." + #: editor/editor_autoload_settings.cpp msgid "Invalid name." msgstr "Ugyldigt navn." @@ -2392,7 +2389,8 @@ msgid "Save & Restart" msgstr "Gem & genstart" #: editor/editor_node.cpp -msgid "Spins when the editor window repaints!" +#, fuzzy +msgid "Spins when the editor window redraws." msgstr "Snurrer nÃ¥r editor vinduer gentegnes!" #: editor/editor_node.cpp @@ -3481,25 +3479,6 @@ msgid "Create Polygon" msgstr "Opret Poly" #: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Edit Polygon" -msgstr "Rediger Poly" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Insert Point" -msgstr "Indsæt Punkt" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Edit Polygon (Remove Point)" -msgstr "Rediger Poly (Fjern Punkt)" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Remove Polygon And Point" -msgstr "Fjern Poly og Punkt" - -#: editor/plugins/abstract_polygon_2d_editor.cpp #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #, fuzzy @@ -3524,6 +3503,25 @@ msgstr "" msgid "Erase points." msgstr "Slet points" +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Edit Polygon" +msgstr "Rediger Poly" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Insert Point" +msgstr "Indsæt Punkt" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Edit Polygon (Remove Point)" +msgstr "Rediger Poly (Fjern Punkt)" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Remove Polygon And Point" +msgstr "Fjern Poly og Punkt" + #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #: editor/plugins/animation_player_editor_plugin.cpp @@ -4329,6 +4327,16 @@ msgid "Move CanvasItem" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp +msgid "Presets for the anchors and margins values of a Control node." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp +msgid "" +"Children of containers have their anchors and margins values overridden by " +"their parent." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp msgid "Anchors only" msgstr "" @@ -5242,6 +5250,12 @@ msgid "Create UV Map" msgstr "" #: editor/plugins/polygon_2d_editor_plugin.cpp +msgid "" +"Polygon 2D has internal vertices, so it can no longer be edited in the " +"viewport." +msgstr "" + +#: editor/plugins/polygon_2d_editor_plugin.cpp #, fuzzy msgid "Create Polygon & UV" msgstr "Opret Poly" @@ -6369,7 +6383,7 @@ msgid "Post" msgstr "" #: editor/plugins/spatial_editor_plugin.cpp -msgid "Name-less gizmo" +msgid "Nameless gizmo" msgstr "" #: editor/plugins/sprite_editor_plugin.cpp @@ -6449,8 +6463,14 @@ msgid "(empty)" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animations" -msgstr "" +#, fuzzy +msgid "Animations:" +msgstr "Tilføj animation" + +#: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "New Animation" +msgstr "Ny Animation Navn:" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed (FPS):" @@ -6461,8 +6481,9 @@ msgid "Loop" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animation Frames" -msgstr "" +#, fuzzy +msgid "Animation Frames:" +msgstr "Ny Animation Navn:" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Insert Empty (Before)" @@ -7283,6 +7304,19 @@ msgstr "" #: editor/project_manager.cpp msgid "" +"The following project settings file does not specify the version of Godot " +"through which it was created.\n" +"\n" +"%s\n" +"\n" +"If you proceed with opening it, it will be converted to Godot's current " +"configuration file format.\n" +"Warning: You will not be able to open the project with previous versions of " +"the engine anymore." +msgstr "" + +#: editor/project_manager.cpp +msgid "" "The following project settings file was generated by an older engine " "version, and needs to be converted for this version:\n" "\n" @@ -8802,10 +8836,6 @@ msgid "Build Project" msgstr "Projekt" #: modules/mono/editor/mono_bottom_panel.cpp -msgid "Warnings" -msgstr "" - -#: modules/mono/editor/mono_bottom_panel.cpp #, fuzzy msgid "View log" msgstr "Vis filer" @@ -9481,6 +9511,13 @@ msgstr "" "ParallaxLayer node virker kun, nÃ¥r den angives som barn af en " "ParallaxBackground node." +#: scene/2d/particles_2d.cpp +msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles2D node instead. You can use the \"Convert to " +"CPUParticles\" option for this purpose." +msgstr "" + #: scene/2d/particles_2d.cpp scene/3d/particles.cpp msgid "" "A material to process the particles is not assigned, so no behavior is " @@ -9651,6 +9688,13 @@ msgstr "" #: scene/3d/particles.cpp msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles node instead. You can use the \"Convert to CPUParticles" +"\" option for this purpose." +msgstr "" + +#: scene/3d/particles.cpp +msgid "" "Nothing is visible because meshes have not been assigned to draw passes." msgstr "" @@ -9683,23 +9727,6 @@ msgstr "" msgid "Path property must point to a valid Spatial node to work." msgstr "Stien skal pege pÃ¥ en gyldig fysisk node for at virke." -#: scene/3d/scenario_fx.cpp -msgid "WorldEnvironment needs an Environment resource." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." -msgstr "" -"Kun én WorldEnvironment er tilladt pr. scene (eller et sæt af instanserede " -"scener)." - -#: scene/3d/scenario_fx.cpp -msgid "" -"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " -"this environment's Background Mode to Canvas (for 2D scenes)." -msgstr "" - #: scene/3d/soft_body.cpp msgid "This body will be ignored until you set a mesh" msgstr "" @@ -9725,6 +9752,23 @@ msgid "" "it as a child of a VehicleBody." msgstr "" +#: scene/3d/world_environment.cpp +msgid "WorldEnvironment needs an Environment resource." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." +msgstr "" +"Kun én WorldEnvironment er tilladt pr. scene (eller et sæt af instanserede " +"scener)." + +#: scene/3d/world_environment.cpp +msgid "" +"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " +"this environment's Background Mode to Canvas (for 2D scenes)." +msgstr "" + #: scene/animation/animation_blend_tree.cpp msgid "On BlendTree node '%s', animation not found: '%s'" msgstr "" @@ -9771,11 +9815,19 @@ msgid "This node has been deprecated. Use AnimationTree instead." msgstr "" #: scene/gui/color_picker.cpp +msgid "Pick a color from the screen." +msgstr "" + +#: scene/gui/color_picker.cpp msgid "Raw Mode" msgstr "" #: scene/gui/color_picker.cpp -msgid "Add current color as a preset" +msgid "Switch between hexadecimal and code values." +msgstr "" + +#: scene/gui/color_picker.cpp +msgid "Add current color as a preset." msgstr "" #: scene/gui/dialogs.cpp @@ -9866,6 +9918,18 @@ msgstr "" msgid "Varyings can only be assigned in vertex function." msgstr "" +#~ msgid "Warnings:" +#~ msgstr "Advarsler:" + +#~ msgid "Font Size:" +#~ msgstr "Skrifttype Størrelse:" + +#~ msgid "Line:" +#~ msgstr "Linje:" + +#~ msgid "Col:" +#~ msgstr "Kol:" + #, fuzzy #~ msgid "OrientedPathFollow only works when set as a child of a Path node." #~ msgstr "" diff --git a/editor/translations/de.po b/editor/translations/de.po index 38f480d548..5ee82b5d7a 100644 --- a/editor/translations/de.po +++ b/editor/translations/de.po @@ -36,12 +36,13 @@ # asyncial <mahlburg@posteo.de>, 2018. # ssantos <ssantos@web.de>, 2018. # Rémi Verschelde <akien@godotengine.org>, 2019. +# Martin <martinreininger@gmx.net>, 2019. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2019-01-26 21:22+0000\n" -"Last-Translator: So Wieso <sowieso@dukun.de>\n" +"PO-Revision-Date: 2019-02-13 23:10+0000\n" +"Last-Translator: Martin <martinreininger@gmx.net>\n" "Language-Team: German <https://hosted.weblate.org/projects/godot-engine/" "godot/de/>\n" "Language: de\n" @@ -576,21 +577,14 @@ msgstr "Verkleinern" msgid "Reset Zoom" msgstr "Vergrößerung zurücksetzen" -#: editor/code_editor.cpp -msgid "Warnings:" -msgstr "Warnungen:" - -#: editor/code_editor.cpp -msgid "Font Size:" -msgstr "Schriftgröße:" - -#: editor/code_editor.cpp -msgid "Line:" -msgstr "Zeile:" +#: editor/code_editor.cpp modules/mono/editor/mono_bottom_panel.cpp +msgid "Warnings" +msgstr "Warnungen" #: editor/code_editor.cpp -msgid "Col:" -msgstr "Spalte:" +#, fuzzy +msgid "Line and column numbers." +msgstr "Zeilen- und Spaltennummern" #: editor/connections_dialog.cpp msgid "Method in target Node must be specified!" @@ -633,7 +627,7 @@ msgstr "Zusätzliche Aufrufparameter:" #: editor/connections_dialog.cpp msgid "Path to Node:" -msgstr "Pfad zur Node:" +msgstr "Pfad zum Node:" #: editor/connections_dialog.cpp msgid "Make Function" @@ -895,8 +889,8 @@ msgstr "Ausgewählte Dateien löschen?" #: editor/dependency_editor.cpp editor/editor_audio_buses.cpp #: editor/editor_file_dialog.cpp editor/editor_node.cpp #: editor/filesystem_dock.cpp editor/plugins/item_list_editor_plugin.cpp -#: editor/project_export.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_dock.cpp +#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp +#: editor/project_settings_editor.cpp editor/scene_tree_dock.cpp msgid "Delete" msgstr "Löschen" @@ -1007,12 +1001,12 @@ msgstr "Inhalte werden entpackt" #: editor/editor_asset_installer.cpp editor/project_manager.cpp msgid "Package installed successfully!" -msgstr "Paket erfolgreich installiert!" +msgstr "Paket wurde erfolgreich installiert!" #: editor/editor_asset_installer.cpp #: editor/plugins/asset_library_editor_plugin.cpp msgid "Success!" -msgstr "Erfolgreich!" +msgstr "Geschafft!" #: editor/editor_asset_installer.cpp #: editor/plugins/asset_library_editor_plugin.cpp @@ -1153,8 +1147,9 @@ msgid "Add Bus" msgstr "Audiobus hinzufügen" #: editor/editor_audio_buses.cpp -msgid "Create a new Bus Layout." -msgstr "Neues Audiobus-Layout erstellen." +#, fuzzy +msgid "Add a new Audio Bus to this layout." +msgstr "Audiobus-Layout speichern als..." #: editor/editor_audio_buses.cpp editor/editor_properties.cpp #: editor/plugins/animation_player_editor_plugin.cpp editor/property_editor.cpp @@ -1182,6 +1177,10 @@ msgstr "Standard laden" msgid "Load the default Bus Layout." msgstr "Standard Bus-Layout laden." +#: editor/editor_audio_buses.cpp +msgid "Create a new Bus Layout." +msgstr "Neues Audiobus-Layout erstellen." + #: editor/editor_autoload_settings.cpp msgid "Invalid name." msgstr "Ungültiger Name." @@ -2440,7 +2439,8 @@ msgid "Save & Restart" msgstr "Speichern & Neu starten" #: editor/editor_node.cpp -msgid "Spins when the editor window repaints!" +#, fuzzy +msgid "Spins when the editor window redraws." msgstr "Dreht sich, wenn das Editorfenster neu gezeichnet wird!" #: editor/editor_node.cpp @@ -2648,7 +2648,7 @@ msgstr "[leer]" #: editor/editor_properties.cpp editor/plugins/root_motion_editor_plugin.cpp msgid "Assign..." -msgstr "Zuweisen.." +msgstr "Zuweisen..." #: editor/editor_properties.cpp msgid "Invalid RID" @@ -3368,17 +3368,20 @@ msgstr "Neuimport" #: editor/import_dock.cpp msgid "Save scenes, re-import and restart" -msgstr "" +msgstr "Szenen speichern, reimportieren und neu starten" #: editor/import_dock.cpp -#, fuzzy msgid "Changing the type of an imported file requires editor restart." -msgstr "Das Ändern des Video-Treibers erfordert einen Neustart des Editors." +msgstr "" +"Den Typ einer importierten Datei zu ändern erfordert einen Neustart des " +"Editors." #: editor/import_dock.cpp msgid "" "WARNING: Assets exist that use this resource, they may stop loading properly." msgstr "" +"ACHTUNG: Es existieren Inhalte die diese Ressource nutzen und nachher " +"möglicherweise nicht mehr ordnungsgemäß laden können." #: editor/inspector_dock.cpp msgid "Failed to load resource." @@ -3503,22 +3506,6 @@ msgid "Create Polygon" msgstr "Polygon erstellen" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Edit Polygon" -msgstr "Polygon bearbeiten" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Insert Point" -msgstr "Punkt einfügen" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Edit Polygon (Remove Point)" -msgstr "Polygon bearbeiten (Punkt entfernen)" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Remove Polygon And Point" -msgstr "Polygon und Punkt entfernen" - -#: editor/plugins/abstract_polygon_2d_editor.cpp #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp msgid "Create points." @@ -3539,6 +3526,22 @@ msgstr "" msgid "Erase points." msgstr "Punkte löschen." +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Edit Polygon" +msgstr "Polygon bearbeiten" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Insert Point" +msgstr "Punkt einfügen" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Edit Polygon (Remove Point)" +msgstr "Polygon bearbeiten (Punkt entfernen)" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Remove Polygon And Point" +msgstr "Polygon und Punkt entfernen" + #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #: editor/plugins/animation_player_editor_plugin.cpp @@ -4342,6 +4345,18 @@ msgid "Move CanvasItem" msgstr "CanvasItem verschieben" #: editor/plugins/canvas_item_editor_plugin.cpp +msgid "Presets for the anchors and margins values of a Control node." +msgstr "Voreinstellungen für die Anker- und Ränderwerte eines Kontroll-Nodes." + +#: editor/plugins/canvas_item_editor_plugin.cpp +msgid "" +"Children of containers have their anchors and margins values overridden by " +"their parent." +msgstr "" +"Bei Containern für Kinder werden die Anker- und Randwerte von ihren Eltern " +"überschrieben." + +#: editor/plugins/canvas_item_editor_plugin.cpp msgid "Anchors only" msgstr "nur Anker" @@ -5254,6 +5269,12 @@ msgid "Create UV Map" msgstr "Erzeuge UV-Map" #: editor/plugins/polygon_2d_editor_plugin.cpp +msgid "" +"Polygon 2D has internal vertices, so it can no longer be edited in the " +"viewport." +msgstr "" + +#: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Create Polygon & UV" msgstr "Polygon und UV erstellen" @@ -6345,7 +6366,7 @@ msgid "Post" msgstr "Nachher" #: editor/plugins/spatial_editor_plugin.cpp -msgid "Name-less gizmo" +msgid "Nameless gizmo" msgstr "Namenloser Anfasser" #: editor/plugins/sprite_editor_plugin.cpp @@ -6423,8 +6444,12 @@ msgid "(empty)" msgstr "(leer)" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animations" -msgstr "Animationen" +msgid "Animations:" +msgstr "Animationen:" + +#: editor/plugins/sprite_frames_editor_plugin.cpp +msgid "New Animation" +msgstr "Neue Animation" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed (FPS):" @@ -6435,8 +6460,8 @@ msgid "Loop" msgstr "Wiederholung" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animation Frames" -msgstr "Animationsframes" +msgid "Animation Frames:" +msgstr "Animationsbilder:" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Insert Empty (Before)" @@ -6763,7 +6788,7 @@ msgstr "Keine Textur zum Entfernen ausgewählt." #: editor/plugins/tile_set_editor_plugin.cpp msgid "Create from scene? This will overwrite all current tiles." -msgstr "Aus Szene erstellen? Alle gegenwärtigen Kacheln werden überschrieben." +msgstr "Aus Szene erstellen? Alle aktuellen Kacheln werden überschrieben!" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Merge from scene?" @@ -6849,7 +6874,7 @@ msgstr "Kachel erstellen" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Set Tile Icon" -msgstr "Kachel-Icon setzen" +msgstr "Kachel Icon zuweisen" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Edit Tile Bitmask" @@ -6873,7 +6898,7 @@ msgstr "Kachel-Bitmaske einfügen" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Clear Tile Bitmask" -msgstr "Kachel-Bitmaske leeren" +msgstr "Kachel Bitmaske löschen" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Remove Tile" @@ -7188,15 +7213,15 @@ msgstr "Projektinstallationspfad:" #: editor/project_manager.cpp msgid "Browse" -msgstr "Durchstöbern" +msgstr "Durchsuchen" #: editor/project_manager.cpp msgid "Renderer:" -msgstr "" +msgstr "Renderer:" #: editor/project_manager.cpp msgid "OpenGL ES 3.0" -msgstr "" +msgstr "OpenGL ES 3.0" #: editor/project_manager.cpp msgid "" @@ -7205,10 +7230,14 @@ msgid "" "Incompatible with older hardware\n" "Not recommended for web games" msgstr "" +"Höhere Grafikqualität\n" +"Alle Funktionen verfügbar\n" +"Inkompatibel mit älterer Hardware\n" +"Nicht empfohlen für Webanwendungen" #: editor/project_manager.cpp msgid "OpenGL ES 2.0" -msgstr "" +msgstr "OpenGL ES 2.0" #: editor/project_manager.cpp msgid "" @@ -7217,10 +7246,16 @@ msgid "" "Works on most hardware\n" "Recommended for web games" msgstr "" +"Geringere Grafikqualität\n" +"Einige Funktionen sind nicht vorhanden\n" +"Läuft auf fast jeder Hardware\n" +"Empfohlen für Webanwendungen" #: editor/project_manager.cpp msgid "Renderer can be changed later, but scenes may need to be adjusted." msgstr "" +"Der Renderer kann auch später noch ausgetauscht werden, allerdings kann es " +"sein, dass dann manche Szenen angepasst werden müssen." #: editor/project_manager.cpp msgid "Unnamed Project" @@ -7236,6 +7271,28 @@ msgstr "Sollen wirklich mehrere Projekte geöffnet werden?" #: editor/project_manager.cpp msgid "" +"The following project settings file does not specify the version of Godot " +"through which it was created.\n" +"\n" +"%s\n" +"\n" +"If you proceed with opening it, it will be converted to Godot's current " +"configuration file format.\n" +"Warning: You will not be able to open the project with previous versions of " +"the engine anymore." +msgstr "" +"Die folgenden Projekteinstellungsdatei enthält keine Information darüber, " +"mit welcher Version von Godot sie erstellt wurde.\n" +"\n" +"%s\n" +"\n" +"Wenn Sie mit dem Öffnen fortfahren, wird die Datei in das aktuelle " +"Konfigurationsdateiformat von Godot konvertiert.\n" +"Warnung: Das Projekt kann nach der Konvertierung nicht mehr mit einer " +"älteren Version geöffnet werden." + +#: editor/project_manager.cpp +msgid "" "The following project settings file was generated by an older engine " "version, and needs to be converted for this version:\n" "\n" @@ -7245,14 +7302,14 @@ msgid "" "Warning: You will not be able to open the project with previous versions of " "the engine anymore." msgstr "" -"Die folgende Projekteinstellungsdatei wurde mit einer älteren Godot-Version " -"erzeugt und muss für die gegenwärtige Version angepasst werden:\n" +"Die Projekteinstellungsdatei ist mit einer älteren Version erstellt worden " +"und muss in die folgende Version konvertiert werden:\n" "\n" "%s\n" "\n" -"Sollen die Anpassungen vorgenommen werden?\n" -"Achtung: Das Projekt kann nach der Anpassung nicht mehr mit einer älteren " -"Godot-Version geöffnet werden." +"Möchten Sie die Konvertierung durchführen?\n" +"Warnung: Das Projekt kann nach der Konvertierung nicht mehr mit einer " +"älteren Version geöffnet werden." #: editor/project_manager.cpp msgid "" @@ -7480,7 +7537,7 @@ msgstr "Ereignis hinzufügen" #: editor/project_settings_editor.cpp msgid "Button" -msgstr "Knopf" +msgstr "Button" #: editor/project_settings_editor.cpp msgid "Left Button." @@ -7953,6 +8010,7 @@ msgstr "Dupliziere Node(s)" #: editor/scene_tree_dock.cpp msgid "Can't reparent nodes in inherited scenes, order of nodes can't change." msgstr "" +"Nodes in geerbtet Szenen können nicht umgehängt oder umgeordnet werden." #: editor/scene_tree_dock.cpp msgid "Node must belong to the edited scene to become root." @@ -8770,10 +8828,6 @@ msgid "Build Project" msgstr "Projekt bauen" #: modules/mono/editor/mono_bottom_panel.cpp -msgid "Warnings" -msgstr "Warnungen" - -#: modules/mono/editor/mono_bottom_panel.cpp msgid "View log" msgstr "Log anschauen" @@ -9457,6 +9511,16 @@ msgstr "" "Das ParallaxLayer-Node lässt sich nur als Unterobjekt eines " "ParallaxBackground-Node verwenden." +#: scene/2d/particles_2d.cpp +msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles2D node instead. You can use the \"Convert to " +"CPUParticles\" option for this purpose." +msgstr "" +"GPU-basierte Partikel werden vom GLES2-Grafiktreiber nicht unterstützt.\n" +"Verwenden Sie stattdessen den CPUParticles2D Node. Sie können dazu die " +"Option \"In CPUPartikel konvertieren\" verwenden." + #: scene/2d/particles_2d.cpp scene/3d/particles.cpp msgid "" "A material to process the particles is not assigned, so no behavior is " @@ -9652,6 +9716,16 @@ msgstr "" #: scene/3d/particles.cpp msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles node instead. You can use the \"Convert to CPUParticles" +"\" option for this purpose." +msgstr "" +"GPU-basierte Partikel werden vom GLES2-Grafiktreiber nicht unterstützt.\n" +"Verwenden Sie stattdessen den CPUParticles Knoten. Sie können dazu die " +"Option \"In CPUPartikel konvertieren\" verwenden." + +#: scene/3d/particles.cpp +msgid "" "Nothing is visible because meshes have not been assigned to draw passes." msgstr "" "Nichts ist sichtbar da keine Meshe den Zeichendurchläufen zugewiesen wurden." @@ -9693,26 +9767,6 @@ msgstr "" msgid "Path property must point to a valid Spatial node to work." msgstr "Die Pfad-Eigenschaft muss auf ein gültiges Spatial-Node verweisen." -#: scene/3d/scenario_fx.cpp -msgid "WorldEnvironment needs an Environment resource." -msgstr "Ein WorldEnvironment benötigt eine Environment-Ressource." - -#: scene/3d/scenario_fx.cpp -msgid "" -"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." -msgstr "" -"Pro Szene (oder einem Satz von instanzierten Szenen) ist nur ein einziges " -"WorldEnvironment erlaubt." - -#: scene/3d/scenario_fx.cpp -msgid "" -"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " -"this environment's Background Mode to Canvas (for 2D scenes)." -msgstr "" -"Dieses WorldEnvironment wird ignoriert. Entweder füge eine Kamera (für 3D-" -"Szenen) hinzu oder setze den Hintergrund-Modus des Environments nach Canvas " -"(für 2D-Szenen)." - #: scene/3d/soft_body.cpp msgid "This body will be ignored until you set a mesh" msgstr "Diese Körper wird ignoriert werden bis ein Mesh gesetzt wurde" @@ -9745,6 +9799,26 @@ msgstr "" "implementieren. Es kann ausschließlich als Unterobjekt von VehicleBody " "verwendet werden." +#: scene/3d/world_environment.cpp +msgid "WorldEnvironment needs an Environment resource." +msgstr "Ein WorldEnvironment benötigt eine Environment-Ressource." + +#: scene/3d/world_environment.cpp +msgid "" +"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." +msgstr "" +"Pro Szene (oder einem Satz von instanzierten Szenen) ist nur ein einziges " +"WorldEnvironment erlaubt." + +#: scene/3d/world_environment.cpp +msgid "" +"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " +"this environment's Background Mode to Canvas (for 2D scenes)." +msgstr "" +"Dieses WorldEnvironment wird ignoriert. Entweder füge eine Kamera (für 3D-" +"Szenen) hinzu oder setze den Hintergrund-Modus des Environments nach Canvas " +"(für 2D-Szenen)." + #: scene/animation/animation_blend_tree.cpp msgid "On BlendTree node '%s', animation not found: '%s'" msgstr "In BlendTree-Node ‚%s‘, Animation nicht gefunden: ‚%s‘" @@ -9792,11 +9866,20 @@ msgstr "" "AnimationTree." #: scene/gui/color_picker.cpp +msgid "Pick a color from the screen." +msgstr "Wählt eine Farbe vom Bildschirm aus." + +#: scene/gui/color_picker.cpp msgid "Raw Mode" msgstr "Rohdatenmodus" #: scene/gui/color_picker.cpp -msgid "Add current color as a preset" +msgid "Switch between hexadecimal and code values." +msgstr "Wechselt zwischen Hexadezimal- und Zahlenwerten." + +#: scene/gui/color_picker.cpp +#, fuzzy +msgid "Add current color as a preset." msgstr "Füge aktuelle Farbe als Vorlage hinzu" #: scene/gui/dialogs.cpp @@ -9895,6 +9978,18 @@ msgstr "Zuweisung an Uniform." msgid "Varyings can only be assigned in vertex function." msgstr "Varyings können nur in Vertex-Funktion zugewiesen werden." +#~ msgid "Warnings:" +#~ msgstr "Warnungen:" + +#~ msgid "Font Size:" +#~ msgstr "Schriftgröße:" + +#~ msgid "Line:" +#~ msgstr "Zeile:" + +#~ msgid "Col:" +#~ msgstr "Spalte:" + #~ msgid "OrientedPathFollow only works when set as a child of a Path node." #~ msgstr "" #~ "OrientedPathFollow funktioniert nur, wenn es als Unterobjekt eines Path-" diff --git a/editor/translations/de_CH.po b/editor/translations/de_CH.po index 1c7fce5965..e324a988d5 100644 --- a/editor/translations/de_CH.po +++ b/editor/translations/de_CH.po @@ -549,20 +549,12 @@ msgstr "" msgid "Reset Zoom" msgstr "" -#: editor/code_editor.cpp -msgid "Warnings:" -msgstr "" - -#: editor/code_editor.cpp -msgid "Font Size:" -msgstr "" - -#: editor/code_editor.cpp -msgid "Line:" +#: editor/code_editor.cpp modules/mono/editor/mono_bottom_panel.cpp +msgid "Warnings" msgstr "" #: editor/code_editor.cpp -msgid "Col:" +msgid "Line and column numbers." msgstr "" #: editor/connections_dialog.cpp @@ -863,8 +855,8 @@ msgstr "" #: editor/dependency_editor.cpp editor/editor_audio_buses.cpp #: editor/editor_file_dialog.cpp editor/editor_node.cpp #: editor/filesystem_dock.cpp editor/plugins/item_list_editor_plugin.cpp -#: editor/project_export.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_dock.cpp +#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp +#: editor/project_settings_editor.cpp editor/scene_tree_dock.cpp msgid "Delete" msgstr "" @@ -1124,7 +1116,7 @@ msgid "Add Bus" msgstr "" #: editor/editor_audio_buses.cpp -msgid "Create a new Bus Layout." +msgid "Add a new Audio Bus to this layout." msgstr "" #: editor/editor_audio_buses.cpp editor/editor_properties.cpp @@ -1153,6 +1145,10 @@ msgstr "" msgid "Load the default Bus Layout." msgstr "" +#: editor/editor_audio_buses.cpp +msgid "Create a new Bus Layout." +msgstr "" + #: editor/editor_autoload_settings.cpp msgid "Invalid name." msgstr "" @@ -2357,7 +2353,7 @@ msgid "Save & Restart" msgstr "Datei speichern" #: editor/editor_node.cpp -msgid "Spins when the editor window repaints!" +msgid "Spins when the editor window redraws." msgstr "" #: editor/editor_node.cpp @@ -3435,25 +3431,6 @@ msgid "Create Polygon" msgstr "Node erstellen" #: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Edit Polygon" -msgstr "Script hinzufügen" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Insert Point" -msgstr "Bild einfügen" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Edit Polygon (Remove Point)" -msgstr "" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Remove Polygon And Point" -msgstr "Ungültige Bilder löschen" - -#: editor/plugins/abstract_polygon_2d_editor.cpp #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #, fuzzy @@ -3473,6 +3450,25 @@ msgstr "" msgid "Erase points." msgstr "Oberfläche %d" +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Edit Polygon" +msgstr "Script hinzufügen" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Insert Point" +msgstr "Bild einfügen" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Edit Polygon (Remove Point)" +msgstr "" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Remove Polygon And Point" +msgstr "Ungültige Bilder löschen" + #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #: editor/plugins/animation_player_editor_plugin.cpp @@ -4282,6 +4278,16 @@ msgid "Move CanvasItem" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp +msgid "Presets for the anchors and margins values of a Control node." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp +msgid "" +"Children of containers have their anchors and margins values overridden by " +"their parent." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp msgid "Anchors only" msgstr "" @@ -5202,6 +5208,12 @@ msgid "Create UV Map" msgstr "" #: editor/plugins/polygon_2d_editor_plugin.cpp +msgid "" +"Polygon 2D has internal vertices, so it can no longer be edited in the " +"viewport." +msgstr "" + +#: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Create Polygon & UV" msgstr "" @@ -6315,7 +6327,7 @@ msgid "Post" msgstr "" #: editor/plugins/spatial_editor_plugin.cpp -msgid "Name-less gizmo" +msgid "Nameless gizmo" msgstr "" #: editor/plugins/sprite_editor_plugin.cpp @@ -6394,8 +6406,14 @@ msgid "(empty)" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animations" -msgstr "" +#, fuzzy +msgid "Animations:" +msgstr "Animations-Node" + +#: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "New Animation" +msgstr "Bild einfügen" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed (FPS):" @@ -6406,8 +6424,9 @@ msgid "Loop" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animation Frames" -msgstr "" +#, fuzzy +msgid "Animation Frames:" +msgstr "Animations-Node" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Insert Empty (Before)" @@ -7235,6 +7254,19 @@ msgstr "" #: editor/project_manager.cpp msgid "" +"The following project settings file does not specify the version of Godot " +"through which it was created.\n" +"\n" +"%s\n" +"\n" +"If you proceed with opening it, it will be converted to Godot's current " +"configuration file format.\n" +"Warning: You will not be able to open the project with previous versions of " +"the engine anymore." +msgstr "" + +#: editor/project_manager.cpp +msgid "" "The following project settings file was generated by an older engine " "version, and needs to be converted for this version:\n" "\n" @@ -8752,10 +8784,6 @@ msgid "Build Project" msgstr "Projektname:" #: modules/mono/editor/mono_bottom_panel.cpp -msgid "Warnings" -msgstr "" - -#: modules/mono/editor/mono_bottom_panel.cpp #, fuzzy msgid "View log" msgstr "Datei(en) öffnen" @@ -9426,6 +9454,13 @@ msgid "" "ParallaxLayer node only works when set as child of a ParallaxBackground node." msgstr "" +#: scene/2d/particles_2d.cpp +msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles2D node instead. You can use the \"Convert to " +"CPUParticles\" option for this purpose." +msgstr "" + #: scene/2d/particles_2d.cpp scene/3d/particles.cpp msgid "" "A material to process the particles is not assigned, so no behavior is " @@ -9588,6 +9623,13 @@ msgstr "" #: scene/3d/particles.cpp msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles node instead. You can use the \"Convert to CPUParticles" +"\" option for this purpose." +msgstr "" + +#: scene/3d/particles.cpp +msgid "" "Nothing is visible because meshes have not been assigned to draw passes." msgstr "" @@ -9622,21 +9664,6 @@ msgstr "" msgid "Path property must point to a valid Spatial node to work." msgstr "Die Pfad-Variable muss auf einen gültigen Particles2D Node verweisen." -#: scene/3d/scenario_fx.cpp -msgid "WorldEnvironment needs an Environment resource." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " -"this environment's Background Mode to Canvas (for 2D scenes)." -msgstr "" - #: scene/3d/soft_body.cpp msgid "This body will be ignored until you set a mesh" msgstr "" @@ -9660,6 +9687,21 @@ msgid "" "it as a child of a VehicleBody." msgstr "" +#: scene/3d/world_environment.cpp +msgid "WorldEnvironment needs an Environment resource." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " +"this environment's Background Mode to Canvas (for 2D scenes)." +msgstr "" + #: scene/animation/animation_blend_tree.cpp msgid "On BlendTree node '%s', animation not found: '%s'" msgstr "" @@ -9702,12 +9744,20 @@ msgid "This node has been deprecated. Use AnimationTree instead." msgstr "" #: scene/gui/color_picker.cpp +msgid "Pick a color from the screen." +msgstr "" + +#: scene/gui/color_picker.cpp #, fuzzy msgid "Raw Mode" msgstr "Node erstellen" #: scene/gui/color_picker.cpp -msgid "Add current color as a preset" +msgid "Switch between hexadecimal and code values." +msgstr "" + +#: scene/gui/color_picker.cpp +msgid "Add current color as a preset." msgstr "" #: scene/gui/dialogs.cpp diff --git a/editor/translations/editor.pot b/editor/translations/editor.pot index 0b271f2739..1565bb3f12 100644 --- a/editor/translations/editor.pot +++ b/editor/translations/editor.pot @@ -526,20 +526,12 @@ msgstr "" msgid "Reset Zoom" msgstr "" -#: editor/code_editor.cpp -msgid "Warnings:" -msgstr "" - -#: editor/code_editor.cpp -msgid "Font Size:" -msgstr "" - -#: editor/code_editor.cpp -msgid "Line:" +#: editor/code_editor.cpp modules/mono/editor/mono_bottom_panel.cpp +msgid "Warnings" msgstr "" #: editor/code_editor.cpp -msgid "Col:" +msgid "Line and column numbers." msgstr "" #: editor/connections_dialog.cpp @@ -833,8 +825,8 @@ msgstr "" #: editor/dependency_editor.cpp editor/editor_audio_buses.cpp #: editor/editor_file_dialog.cpp editor/editor_node.cpp #: editor/filesystem_dock.cpp editor/plugins/item_list_editor_plugin.cpp -#: editor/project_export.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_dock.cpp +#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp +#: editor/project_settings_editor.cpp editor/scene_tree_dock.cpp msgid "Delete" msgstr "" @@ -1086,7 +1078,7 @@ msgid "Add Bus" msgstr "" #: editor/editor_audio_buses.cpp -msgid "Create a new Bus Layout." +msgid "Add a new Audio Bus to this layout." msgstr "" #: editor/editor_audio_buses.cpp editor/editor_properties.cpp @@ -1115,6 +1107,10 @@ msgstr "" msgid "Load the default Bus Layout." msgstr "" +#: editor/editor_audio_buses.cpp +msgid "Create a new Bus Layout." +msgstr "" + #: editor/editor_autoload_settings.cpp msgid "Invalid name." msgstr "" @@ -2285,7 +2281,7 @@ msgid "Save & Restart" msgstr "" #: editor/editor_node.cpp -msgid "Spins when the editor window repaints!" +msgid "Spins when the editor window redraws." msgstr "" #: editor/editor_node.cpp @@ -3323,37 +3319,37 @@ msgid "Create Polygon" msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Edit Polygon" +#: editor/plugins/animation_blend_space_1d_editor.cpp +#: editor/plugins/animation_blend_space_2d_editor.cpp +msgid "Create points." msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Insert Point" +msgid "" +"Edit points.\n" +"LMB: Move Point\n" +"RMB: Erase Point" msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Edit Polygon (Remove Point)" +#: editor/plugins/animation_blend_space_1d_editor.cpp +msgid "Erase points." msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Remove Polygon And Point" +msgid "Edit Polygon" msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -#: editor/plugins/animation_blend_space_1d_editor.cpp -#: editor/plugins/animation_blend_space_2d_editor.cpp -msgid "Create points." +msgid "Insert Point" msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "" -"Edit points.\n" -"LMB: Move Point\n" -"RMB: Erase Point" +msgid "Edit Polygon (Remove Point)" msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -#: editor/plugins/animation_blend_space_1d_editor.cpp -msgid "Erase points." +msgid "Remove Polygon And Point" msgstr "" #: editor/plugins/animation_blend_space_1d_editor.cpp @@ -4136,6 +4132,16 @@ msgid "Move CanvasItem" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp +msgid "Presets for the anchors and margins values of a Control node." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp +msgid "" +"Children of containers have their anchors and margins values overridden by " +"their parent." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp msgid "Anchors only" msgstr "" @@ -5031,6 +5037,12 @@ msgid "Create UV Map" msgstr "" #: editor/plugins/polygon_2d_editor_plugin.cpp +msgid "" +"Polygon 2D has internal vertices, so it can no longer be edited in the " +"viewport." +msgstr "" + +#: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Create Polygon & UV" msgstr "" @@ -6112,7 +6124,7 @@ msgid "Post" msgstr "" #: editor/plugins/spatial_editor_plugin.cpp -msgid "Name-less gizmo" +msgid "Nameless gizmo" msgstr "" #: editor/plugins/sprite_editor_plugin.cpp @@ -6188,7 +6200,11 @@ msgid "(empty)" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animations" +msgid "Animations:" +msgstr "" + +#: editor/plugins/sprite_frames_editor_plugin.cpp +msgid "New Animation" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp @@ -6200,7 +6216,7 @@ msgid "Loop" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animation Frames" +msgid "Animation Frames:" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp @@ -6976,6 +6992,19 @@ msgstr "" #: editor/project_manager.cpp msgid "" +"The following project settings file does not specify the version of Godot " +"through which it was created.\n" +"\n" +"%s\n" +"\n" +"If you proceed with opening it, it will be converted to Godot's current " +"configuration file format.\n" +"Warning: You will not be able to open the project with previous versions of " +"the engine anymore." +msgstr "" + +#: editor/project_manager.cpp +msgid "" "The following project settings file was generated by an older engine " "version, and needs to be converted for this version:\n" "\n" @@ -8452,10 +8481,6 @@ msgid "Build Project" msgstr "" #: modules/mono/editor/mono_bottom_panel.cpp -msgid "Warnings" -msgstr "" - -#: modules/mono/editor/mono_bottom_panel.cpp msgid "View log" msgstr "" @@ -9081,6 +9106,13 @@ msgid "" "ParallaxLayer node only works when set as child of a ParallaxBackground node." msgstr "" +#: scene/2d/particles_2d.cpp +msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles2D node instead. You can use the \"Convert to " +"CPUParticles\" option for this purpose." +msgstr "" + #: scene/2d/particles_2d.cpp scene/3d/particles.cpp msgid "" "A material to process the particles is not assigned, so no behavior is " @@ -9236,6 +9268,13 @@ msgstr "" #: scene/3d/particles.cpp msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles node instead. You can use the \"Convert to CPUParticles" +"\" option for this purpose." +msgstr "" + +#: scene/3d/particles.cpp +msgid "" "Nothing is visible because meshes have not been assigned to draw passes." msgstr "" @@ -9266,21 +9305,6 @@ msgstr "" msgid "Path property must point to a valid Spatial node to work." msgstr "" -#: scene/3d/scenario_fx.cpp -msgid "WorldEnvironment needs an Environment resource." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " -"this environment's Background Mode to Canvas (for 2D scenes)." -msgstr "" - #: scene/3d/soft_body.cpp msgid "This body will be ignored until you set a mesh" msgstr "" @@ -9304,6 +9328,21 @@ msgid "" "it as a child of a VehicleBody." msgstr "" +#: scene/3d/world_environment.cpp +msgid "WorldEnvironment needs an Environment resource." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " +"this environment's Background Mode to Canvas (for 2D scenes)." +msgstr "" + #: scene/animation/animation_blend_tree.cpp msgid "On BlendTree node '%s', animation not found: '%s'" msgstr "" @@ -9345,11 +9384,19 @@ msgid "This node has been deprecated. Use AnimationTree instead." msgstr "" #: scene/gui/color_picker.cpp +msgid "Pick a color from the screen." +msgstr "" + +#: scene/gui/color_picker.cpp msgid "Raw Mode" msgstr "" #: scene/gui/color_picker.cpp -msgid "Add current color as a preset" +msgid "Switch between hexadecimal and code values." +msgstr "" + +#: scene/gui/color_picker.cpp +msgid "Add current color as a preset." msgstr "" #: scene/gui/dialogs.cpp diff --git a/editor/translations/el.po b/editor/translations/el.po index 28fc945310..4895fc6b98 100644 --- a/editor/translations/el.po +++ b/editor/translations/el.po @@ -546,22 +546,13 @@ msgstr "ΣμÏκÏινση" msgid "Reset Zoom" msgstr "ΕπαναφοÏά μεγÎθυνσης" -#: editor/code_editor.cpp -msgid "Warnings:" -msgstr "Î Ïοειδοποιήσεις:" - -#: editor/code_editor.cpp -#, fuzzy -msgid "Font Size:" -msgstr "ΜÎγεθος πηγαίας γÏαμματοσειÏάς:" - -#: editor/code_editor.cpp -msgid "Line:" -msgstr "ΓÏαμμή:" +#: editor/code_editor.cpp modules/mono/editor/mono_bottom_panel.cpp +msgid "Warnings" +msgstr "Î Ïοειδοποιήσεις" #: editor/code_editor.cpp -msgid "Col:" -msgstr "Στήλη:" +msgid "Line and column numbers." +msgstr "" #: editor/connections_dialog.cpp msgid "Method in target Node must be specified!" @@ -866,8 +857,8 @@ msgstr "ΔιαγÏαφή επιλεγμÎνων αÏχείων;" #: editor/dependency_editor.cpp editor/editor_audio_buses.cpp #: editor/editor_file_dialog.cpp editor/editor_node.cpp #: editor/filesystem_dock.cpp editor/plugins/item_list_editor_plugin.cpp -#: editor/project_export.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_dock.cpp +#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp +#: editor/project_settings_editor.cpp editor/scene_tree_dock.cpp msgid "Delete" msgstr "ΔιαγÏαφή" @@ -1125,8 +1116,9 @@ msgid "Add Bus" msgstr "Î Ïοσθήκη διαÏλου" #: editor/editor_audio_buses.cpp -msgid "Create a new Bus Layout." -msgstr "ΔημιουÏγία νÎας διάταξης διαÏλων ήχου." +#, fuzzy +msgid "Add a new Audio Bus to this layout." +msgstr "Αποθήκευση διάταξης διαÏλων ήχου ÏŽÏ‚..." #: editor/editor_audio_buses.cpp editor/editor_properties.cpp #: editor/plugins/animation_player_editor_plugin.cpp editor/property_editor.cpp @@ -1154,6 +1146,10 @@ msgstr "ΦόÏτωση Ï€Ïοεπιλογής" msgid "Load the default Bus Layout." msgstr "ΦόÏτωση Ï€ÏοεπιλεγμÎνης διάταξης διαÏλων ήχου." +#: editor/editor_audio_buses.cpp +msgid "Create a new Bus Layout." +msgstr "ΔημιουÏγία νÎας διάταξης διαÏλων ήχου." + #: editor/editor_autoload_settings.cpp msgid "Invalid name." msgstr "Μη ÎγκυÏο όνομα." @@ -2436,7 +2432,8 @@ msgid "Save & Restart" msgstr "Αποθήκευση & Επανεκκίνηση" #: editor/editor_node.cpp -msgid "Spins when the editor window repaints!" +#, fuzzy +msgid "Spins when the editor window redraws." msgstr "ΠεÏιστÏÎφεται όταν το παÏάθυÏο του επεξεÏγαστή επαναχÏωματίζεται!" #: editor/editor_node.cpp @@ -3510,25 +3507,6 @@ msgid "Create Polygon" msgstr "Δημιουγία πολυγώνου" #: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Edit Polygon" -msgstr "ΕπεγεÏγασία πολυγώνου" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Insert Point" -msgstr "Εισαγωγή σημείου" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Edit Polygon (Remove Point)" -msgstr "ΕπεγεÏγασία πολυγώνου (ΑφαίÏεση σημείου)" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Remove Polygon And Point" -msgstr "ΑφαίÏεση πολυγώνου και σημείου" - -#: editor/plugins/abstract_polygon_2d_editor.cpp #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp msgid "Create points." @@ -3551,6 +3529,25 @@ msgstr "" msgid "Erase points." msgstr "ΔιαγÏαφή σημείων." +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Edit Polygon" +msgstr "ΕπεγεÏγασία πολυγώνου" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Insert Point" +msgstr "Εισαγωγή σημείου" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Edit Polygon (Remove Point)" +msgstr "ΕπεγεÏγασία πολυγώνου (ΑφαίÏεση σημείου)" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Remove Polygon And Point" +msgstr "ΑφαίÏεση πολυγώνου και σημείου" + #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #: editor/plugins/animation_player_editor_plugin.cpp @@ -4360,6 +4357,16 @@ msgid "Move CanvasItem" msgstr "Μετακίνηση CanvasItem" #: editor/plugins/canvas_item_editor_plugin.cpp +msgid "Presets for the anchors and margins values of a Control node." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp +msgid "" +"Children of containers have their anchors and margins values overridden by " +"their parent." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp msgid "Anchors only" msgstr "Μόνο άγκυÏες" @@ -5274,6 +5281,12 @@ msgid "Create UV Map" msgstr "ΔημιουÏγία χάÏτη UV" #: editor/plugins/polygon_2d_editor_plugin.cpp +msgid "" +"Polygon 2D has internal vertices, so it can no longer be edited in the " +"viewport." +msgstr "" + +#: editor/plugins/polygon_2d_editor_plugin.cpp #, fuzzy msgid "Create Polygon & UV" msgstr "Δημιουγία πολυγώνου" @@ -6416,7 +6429,7 @@ msgid "Post" msgstr "Μετά" #: editor/plugins/spatial_editor_plugin.cpp -msgid "Name-less gizmo" +msgid "Nameless gizmo" msgstr "" #: editor/plugins/sprite_editor_plugin.cpp @@ -6499,10 +6512,16 @@ msgid "(empty)" msgstr "(άδειο)" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animations" +#, fuzzy +msgid "Animations:" msgstr "Κινήσεις" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "New Animation" +msgstr "Κίνηση" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed (FPS):" msgstr "ΤαχÏτητα (FPS):" @@ -6511,7 +6530,8 @@ msgid "Loop" msgstr "Επανάληψη" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animation Frames" +#, fuzzy +msgid "Animation Frames:" msgstr "ΚαÏΠκίνησης" #: editor/plugins/sprite_frames_editor_plugin.cpp @@ -7357,6 +7377,19 @@ msgstr "Είστε σίγουÏοι πως θÎλετε να ανοίξετε Ï€ #: editor/project_manager.cpp msgid "" +"The following project settings file does not specify the version of Godot " +"through which it was created.\n" +"\n" +"%s\n" +"\n" +"If you proceed with opening it, it will be converted to Godot's current " +"configuration file format.\n" +"Warning: You will not be able to open the project with previous versions of " +"the engine anymore." +msgstr "" + +#: editor/project_manager.cpp +msgid "" "The following project settings file was generated by an older engine " "version, and needs to be converted for this version:\n" "\n" @@ -8923,10 +8956,6 @@ msgid "Build Project" msgstr "Δόμηση ÎÏγου" #: modules/mono/editor/mono_bottom_panel.cpp -msgid "Warnings" -msgstr "Î Ïοειδοποιήσεις" - -#: modules/mono/editor/mono_bottom_panel.cpp msgid "View log" msgstr "Î Ïοβολή αÏχείου καταγÏαφής" @@ -9607,6 +9636,13 @@ msgstr "" "Ένας κόμβος ParallaxLayer δουλεÏει μόνο όταν κληÏονομεί Îναν κόμβο Ï„Ïπου " "ParallaxBackground." +#: scene/2d/particles_2d.cpp +msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles2D node instead. You can use the \"Convert to " +"CPUParticles\" option for this purpose." +msgstr "" + #: scene/2d/particles_2d.cpp scene/3d/particles.cpp msgid "" "A material to process the particles is not assigned, so no behavior is " @@ -9796,6 +9832,13 @@ msgstr "" #: scene/3d/particles.cpp msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles node instead. You can use the \"Convert to CPUParticles" +"\" option for this purpose." +msgstr "" + +#: scene/3d/particles.cpp +msgid "" "Nothing is visible because meshes have not been assigned to draw passes." msgstr "" "Τίποτα δεν είναι οÏατό, επειδή δεν Îχουν οÏιστεί πεÏάσματα για τα πλÎγματα." @@ -9833,25 +9876,6 @@ msgstr "" "Η ιδιότητα Path Ï€ÏÎπει να δείχνει σε Îναν ÎγκυÏο κόμβο Spatial για να " "δουλÎψει αυτός ο κόμβος." -#: scene/3d/scenario_fx.cpp -msgid "WorldEnvironment needs an Environment resource." -msgstr "Το WorldEnvironment χÏειάζεται Îναν πόÏο Environment." - -#: scene/3d/scenario_fx.cpp -msgid "" -"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." -msgstr "" -"Μόνο Îνα WorldEnvironment επιτÏÎπεται σε κάθε σκηνή (ή σÏνολο στιγμιοτÏπων " -"σκηνών)." - -#: scene/3d/scenario_fx.cpp -msgid "" -"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " -"this environment's Background Mode to Canvas (for 2D scenes)." -msgstr "" -"Αυτό το WorldEnvironment θα αγνοηθεί. Î ÏοσθÎστε μια κάμεÏα (για 3d) ή οÏίστε " -"το Background Mode Î±Ï…Ï„Î¿Ï Ï„Î¿Ï… πεÏιβάλλοντος σε Canvas (για 2d)." - #: scene/3d/soft_body.cpp msgid "This body will be ignored until you set a mesh" msgstr "" @@ -9883,6 +9907,25 @@ msgstr "" "Το VehicleWheel δίνει Îνα σÏστημα Ï„Ïοχών για το VehicleBody. ΠαÏακαλοÏμε " "χÏησιμοποιήστε το ως παιδί του VehicleBody." +#: scene/3d/world_environment.cpp +msgid "WorldEnvironment needs an Environment resource." +msgstr "Το WorldEnvironment χÏειάζεται Îναν πόÏο Environment." + +#: scene/3d/world_environment.cpp +msgid "" +"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." +msgstr "" +"Μόνο Îνα WorldEnvironment επιτÏÎπεται σε κάθε σκηνή (ή σÏνολο στιγμιοτÏπων " +"σκηνών)." + +#: scene/3d/world_environment.cpp +msgid "" +"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " +"this environment's Background Mode to Canvas (for 2D scenes)." +msgstr "" +"Αυτό το WorldEnvironment θα αγνοηθεί. Î ÏοσθÎστε μια κάμεÏα (για 3d) ή οÏίστε " +"το Background Mode Î±Ï…Ï„Î¿Ï Ï„Î¿Ï… πεÏιβάλλοντος σε Canvas (για 2d)." + #: scene/animation/animation_blend_tree.cpp msgid "On BlendTree node '%s', animation not found: '%s'" msgstr "" @@ -9931,11 +9974,20 @@ msgid "This node has been deprecated. Use AnimationTree instead." msgstr "" #: scene/gui/color_picker.cpp +msgid "Pick a color from the screen." +msgstr "" + +#: scene/gui/color_picker.cpp msgid "Raw Mode" msgstr "Ωμή λειτουÏγία" #: scene/gui/color_picker.cpp -msgid "Add current color as a preset" +msgid "Switch between hexadecimal and code values." +msgstr "" + +#: scene/gui/color_picker.cpp +#, fuzzy +msgid "Add current color as a preset." msgstr "Î Ïοσθήκη του Ï„ÏÎχοντος χÏώματος ως Ï€ÏοκαθοÏισμÎνο" #: scene/gui/dialogs.cpp @@ -10033,6 +10085,19 @@ msgstr "" msgid "Varyings can only be assigned in vertex function." msgstr "" +#~ msgid "Warnings:" +#~ msgstr "Î Ïοειδοποιήσεις:" + +#, fuzzy +#~ msgid "Font Size:" +#~ msgstr "ΜÎγεθος πηγαίας γÏαμματοσειÏάς:" + +#~ msgid "Line:" +#~ msgstr "ΓÏαμμή:" + +#~ msgid "Col:" +#~ msgstr "Στήλη:" + #, fuzzy #~ msgid "OrientedPathFollow only works when set as a child of a Path node." #~ msgstr "Το PathFollow2D δουλεÏει μόνο όταν κληÏονομεί Îναν κόμβο Path2D." diff --git a/editor/translations/es.po b/editor/translations/es.po index b00045e09c..fd7e0c46e5 100644 --- a/editor/translations/es.po +++ b/editor/translations/es.po @@ -12,9 +12,9 @@ # David Couto <davidcouto@gmail.com>, 2017. # Dharkael <izhe@hotmail.es>, 2017, 2019. # Diego López <diegodario21@gmail.com>, 2017. -# eon-s <emanuel.segretin@gmail.com>, 2018. +# eon-s <emanuel.segretin@gmail.com>, 2018, 2019. # Gustavo Leon <gleondiaz@gmail.com>, 2017-2018. -# Javier Ocampos <xavier.ocampos@gmail.com>, 2018. +# Javier Ocampos <xavier.ocampos@gmail.com>, 2018, 2019. # Jose Maria Martinez <josemar1992@hotmail.com>, 2018. # Juan Quiroga <juanquiroga9@gmail.com>, 2017. # Kiji Pixel <raccoon.fella@gmail.com>, 2017. @@ -42,8 +42,8 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2019-01-26 21:22+0000\n" -"Last-Translator: Dharkael <izhe@hotmail.es>\n" +"PO-Revision-Date: 2019-02-13 07:10+0000\n" +"Last-Translator: Javier Ocampos <xavier.ocampos@gmail.com>\n" "Language-Team: Spanish <https://hosted.weblate.org/projects/godot-engine/" "godot/es/>\n" "Language: es\n" @@ -68,12 +68,11 @@ msgstr "" #: core/math/expression.cpp msgid "Invalid input %i (not passed) in expression" -msgstr "Entrada inválida %i (no pasado) en expresión" +msgstr "Entrada inválida %i (no se transmitió) en la expresión" #: core/math/expression.cpp msgid "self can't be used because instance is null (not passed)" -msgstr "" -"self no puede ser usado ya que la instancia es nula (no ha sido pasada)" +msgstr "self no puede ser usado ya que la instancia es nula (no pasó)" #: core/math/expression.cpp msgid "Invalid operands to operator %s, %s and %s." @@ -463,7 +462,7 @@ msgstr "Usar Curvas Bezier" #: editor/animation_track_editor.cpp msgid "Anim. Optimizer" -msgstr "Optimizar animación" +msgstr "Optimizador de animación" #: editor/animation_track_editor.cpp msgid "Max. Linear Error:" @@ -581,21 +580,14 @@ msgstr "Alejar" msgid "Reset Zoom" msgstr "Restablecer zoom" -#: editor/code_editor.cpp -msgid "Warnings:" -msgstr "Advertencias:" - -#: editor/code_editor.cpp -msgid "Font Size:" -msgstr "Tamaño de la tipografÃa:" - -#: editor/code_editor.cpp -msgid "Line:" -msgstr "LÃnea:" +#: editor/code_editor.cpp modules/mono/editor/mono_bottom_panel.cpp +msgid "Warnings" +msgstr "Advertencias" #: editor/code_editor.cpp -msgid "Col:" -msgstr "Columna:" +#, fuzzy +msgid "Line and column numbers." +msgstr "Números de lÃnea y columna" #: editor/connections_dialog.cpp msgid "Method in target Node must be specified!" @@ -630,7 +622,7 @@ msgstr "Quitar" #: editor/connections_dialog.cpp msgid "Add Extra Call Argument:" -msgstr "Añadir argumento extra de llamada:" +msgstr "Añadir Argumento de Llamada Extra:" #: editor/connections_dialog.cpp msgid "Extra Call Arguments:" @@ -701,7 +693,8 @@ msgstr "Editar Conexión: " #: editor/connections_dialog.cpp msgid "Are you sure you want to remove all connections from the \"%s\" signal?" -msgstr "¿Está seguro/a que quiere quitar todas las conexiones de esta señal?" +msgstr "" +"¿Estás seguro/a que quieres quitar todas las conexiones de la señal \"%s\"?" #: editor/connections_dialog.cpp editor/editor_help.cpp editor/node_dock.cpp msgid "Signals" @@ -897,8 +890,8 @@ msgstr "¿Eliminar los archivos seleccionados?" #: editor/dependency_editor.cpp editor/editor_audio_buses.cpp #: editor/editor_file_dialog.cpp editor/editor_node.cpp #: editor/filesystem_dock.cpp editor/plugins/item_list_editor_plugin.cpp -#: editor/project_export.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_dock.cpp +#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp +#: editor/project_settings_editor.cpp editor/scene_tree_dock.cpp msgid "Delete" msgstr "Eliminar" @@ -1154,8 +1147,9 @@ msgid "Add Bus" msgstr "Añadir bus" #: editor/editor_audio_buses.cpp -msgid "Create a new Bus Layout." -msgstr "Crear nueva configuración de bus." +#, fuzzy +msgid "Add a new Audio Bus to this layout." +msgstr "Guardar configuración de bus de audio como..." #: editor/editor_audio_buses.cpp editor/editor_properties.cpp #: editor/plugins/animation_player_editor_plugin.cpp editor/property_editor.cpp @@ -1183,6 +1177,10 @@ msgstr "Cargar ajuste predeterminado" msgid "Load the default Bus Layout." msgstr "Cargar configuración de bus por defecto." +#: editor/editor_audio_buses.cpp +msgid "Create a new Bus Layout." +msgstr "Crear nueva configuración de bus." + #: editor/editor_autoload_settings.cpp msgid "Invalid name." msgstr "Nombre inválido." @@ -1325,11 +1323,9 @@ msgid "Storing File:" msgstr "Archivo de almacenamiento:" #: editor/editor_export.cpp -#, fuzzy msgid "No export template found at the expected path:" msgstr "" -"No se han encontrado plantillas de exportación.\n" -"Tienes que descargar e instalarlas para continuar." +"No se ha encontrado ninguna plantilla de exportación en la ruta esperada:" #: editor/editor_export.cpp msgid "Packing" @@ -1338,16 +1334,14 @@ msgstr "Empaquetando" #: editor/editor_export.cpp platform/android/export/export.cpp #: platform/iphone/export/export.cpp platform/javascript/export/export.cpp #: platform/osx/export/export.cpp platform/uwp/export/export.cpp -#, fuzzy msgid "Custom debug template not found." -msgstr "No se ha encontrado ningún paquete de depuración personalizado." +msgstr "No se ha encontrado la plantilla de depuración personalizada." #: editor/editor_export.cpp platform/android/export/export.cpp #: platform/iphone/export/export.cpp platform/javascript/export/export.cpp #: platform/osx/export/export.cpp platform/uwp/export/export.cpp -#, fuzzy msgid "Custom release template not found." -msgstr "No se ha encontrado ningún paquete final personalizado." +msgstr "No se ha encontrado ninguna plantilla de lanzamineto personalizada." #: editor/editor_export.cpp platform/javascript/export/export.cpp msgid "Template file not found:" @@ -1764,7 +1758,7 @@ msgstr "" #: editor/editor_node.cpp editor/scene_tree_dock.cpp msgid "Can't overwrite scene that is still open!" -msgstr "¡No se puede sobreescribir una escena que está abierta!" +msgstr "¡No se puede sobrescribir una escena que todavÃa está abierta!" #: editor/editor_node.cpp msgid "Can't load MeshLibrary for merging!" @@ -2444,7 +2438,8 @@ msgid "Save & Restart" msgstr "Guardar y Reiniciar" #: editor/editor_node.cpp -msgid "Spins when the editor window repaints!" +#, fuzzy +msgid "Spins when the editor window redraws." msgstr "¡Gira cuando la ventana del editor redibuja!" #: editor/editor_node.cpp @@ -2466,7 +2461,7 @@ msgstr "Importar" #: editor/editor_node.cpp msgid "FileSystem" -msgstr "Sistema de archivos" +msgstr "Sistema de Archivos" #: editor/editor_node.cpp msgid "Inspector" @@ -3375,17 +3370,18 @@ msgstr "Reimportar" #: editor/import_dock.cpp msgid "Save scenes, re-import and restart" -msgstr "" +msgstr "Guardar escenas, reimportar y reiniciar" #: editor/import_dock.cpp -#, fuzzy msgid "Changing the type of an imported file requires editor restart." -msgstr "Cambiar el driver de video requiere reiniciar el editor." +msgstr "Cambiar el tipo de un archivo importado requiere reiniciar el editor." #: editor/import_dock.cpp msgid "" "WARNING: Assets exist that use this resource, they may stop loading properly." msgstr "" +"ADVERTENCIA: Existen recursos que utilizan este recurso, pueden dejar de " +"cargar correctamente." #: editor/inspector_dock.cpp msgid "Failed to load resource." @@ -3510,22 +3506,6 @@ msgid "Create Polygon" msgstr "Crear polÃgono" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Edit Polygon" -msgstr "Editar PolÃgono" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Insert Point" -msgstr "Insertar punto" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Edit Polygon (Remove Point)" -msgstr "Editar PolÃgono (Remover Punto)" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Remove Polygon And Point" -msgstr "Remover PolÃgono y Punto" - -#: editor/plugins/abstract_polygon_2d_editor.cpp #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp msgid "Create points." @@ -3546,6 +3526,22 @@ msgstr "" msgid "Erase points." msgstr "Borrar puntos." +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Edit Polygon" +msgstr "Editar PolÃgono" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Insert Point" +msgstr "Insertar punto" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Edit Polygon (Remove Point)" +msgstr "Editar PolÃgono (Remover Punto)" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Remove Polygon And Point" +msgstr "Remover PolÃgono y Punto" + #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #: editor/plugins/animation_player_editor_plugin.cpp @@ -3967,7 +3963,7 @@ msgstr "Transición: " #: editor/plugins/animation_tree_editor_plugin.cpp #: editor/plugins/animation_tree_player_editor_plugin.cpp msgid "AnimationTree" -msgstr "Ãrbol de animación" +msgstr "AnimationTree" #: editor/plugins/animation_tree_player_editor_plugin.cpp msgid "New name:" @@ -4352,6 +4348,18 @@ msgid "Move CanvasItem" msgstr "Mover CanvasItem" #: editor/plugins/canvas_item_editor_plugin.cpp +msgid "Presets for the anchors and margins values of a Control node." +msgstr "Presets para los valores de anclajes y márgenes de un nodo Control." + +#: editor/plugins/canvas_item_editor_plugin.cpp +msgid "" +"Children of containers have their anchors and margins values overridden by " +"their parent." +msgstr "" +"Los hijos de los contenedores tienen sus anclas y valores de márgenes " +"anulados por sus padres." + +#: editor/plugins/canvas_item_editor_plugin.cpp msgid "Anchors only" msgstr "Sólo anclado" @@ -5265,6 +5273,12 @@ msgid "Create UV Map" msgstr "Crear mapa UV" #: editor/plugins/polygon_2d_editor_plugin.cpp +msgid "" +"Polygon 2D has internal vertices, so it can no longer be edited in the " +"viewport." +msgstr "" + +#: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Create Polygon & UV" msgstr "Crear PolÃgono y UV" @@ -6251,31 +6265,31 @@ msgstr "Ajustar objeto al suelo" #: editor/plugins/spatial_editor_plugin.cpp msgid "Transform Dialog..." -msgstr "Dialogo de transformación..." +msgstr "Dialogo de Transformación..." #: editor/plugins/spatial_editor_plugin.cpp msgid "1 Viewport" -msgstr "1 viewport" +msgstr "1 Viewport" #: editor/plugins/spatial_editor_plugin.cpp msgid "2 Viewports" -msgstr "2 viewports" +msgstr "2 Viewports" #: editor/plugins/spatial_editor_plugin.cpp msgid "2 Viewports (Alt)" -msgstr "2 viewports (Alt)" +msgstr "2 Viewports (Alt)" #: editor/plugins/spatial_editor_plugin.cpp msgid "3 Viewports" -msgstr "3 viewports" +msgstr "3 Viewports" #: editor/plugins/spatial_editor_plugin.cpp msgid "3 Viewports (Alt)" -msgstr "3 viewports (Alt)" +msgstr "3 Viewports (Alt)" #: editor/plugins/spatial_editor_plugin.cpp msgid "4 Viewports" -msgstr "4 viewports" +msgstr "4 Viewports" #: editor/plugins/spatial_editor_plugin.cpp msgid "Gizmos" @@ -6355,7 +6369,7 @@ msgid "Post" msgstr "Posterior" #: editor/plugins/spatial_editor_plugin.cpp -msgid "Name-less gizmo" +msgid "Nameless gizmo" msgstr "Gizmo sin nombre" #: editor/plugins/sprite_editor_plugin.cpp @@ -6431,8 +6445,12 @@ msgid "(empty)" msgstr "(vacÃo)" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animations" -msgstr "Animaciones" +msgid "Animations:" +msgstr "Animaciones:" + +#: editor/plugins/sprite_frames_editor_plugin.cpp +msgid "New Animation" +msgstr "Nueva Animación" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed (FPS):" @@ -6443,8 +6461,8 @@ msgid "Loop" msgstr "Repetir" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animation Frames" -msgstr "Fotogramas de animación" +msgid "Animation Frames:" +msgstr "Fotogramas de animación:" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Insert Empty (Before)" @@ -6847,7 +6865,7 @@ msgstr "" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Set Tile Region" -msgstr "Establecer región del Tile" +msgstr "Establecer Región de Tile" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Create Tile" @@ -6855,31 +6873,31 @@ msgstr "Crear Tile" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Set Tile Icon" -msgstr "Establecer icono del Tile" +msgstr "Establecer Icono de Tile" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Edit Tile Bitmask" -msgstr "Editar máscara de bits del Tile" +msgstr "Editar Máscara de Bits de Tile" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Edit Collision Polygon" -msgstr "Editar polÃgono de colisión" +msgstr "Editar PolÃgono de Colisión" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Edit Occlusion Polygon" -msgstr "Editar PolÃgono de oclusión" +msgstr "Editar PolÃgono de Oclusión" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Edit Navigation Polygon" -msgstr "Editar polÃgono de navegación" +msgstr "Editar PolÃgono de Navegación" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Paste Tile Bitmask" -msgstr "Pegar máscara de bits del Tile" +msgstr "Pegar Máscara de Bits de Tile" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Clear Tile Bitmask" -msgstr "Eliminar máscara de bits del Tile" +msgstr "Reestablecer Máscara de Bits de Tile" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Remove Tile" @@ -6887,31 +6905,31 @@ msgstr "Eliminar Tile" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Remove Collision Polygon" -msgstr "Eliminar polÃgono de colisión" +msgstr "Eliminar PolÃgono de Colisión" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Remove Occlusion Polygon" -msgstr "Crear polÃgono de oclusión" +msgstr "Eliminar PolÃgono de Oclusión" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Remove Navigation Polygon" -msgstr "Crear polÃgono de navegación" +msgstr "Crear PolÃgono de Navegación" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Edit Tile Priority" -msgstr "Editar prioridad del Tile" +msgstr "Editar Prioridad del Tile" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Edit Tile Z Index" -msgstr "Editar Indice-Z del Tile" +msgstr "Editar Z Index de Tile" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Create Collision Polygon" -msgstr "Crear polÃgono de colisión" +msgstr "Crear PolÃgono de Colisión" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Create Occlusion Polygon" -msgstr "Crear polÃgono de oclusión" +msgstr "Crear PolÃgono de Oclusión" #: editor/plugins/tile_set_editor_plugin.cpp msgid "This property can't be changed." @@ -7199,11 +7217,11 @@ msgstr "Examinar" #: editor/project_manager.cpp msgid "Renderer:" -msgstr "" +msgstr "Renderizador:" #: editor/project_manager.cpp msgid "OpenGL ES 3.0" -msgstr "" +msgstr "OpenGL ES 3.0" #: editor/project_manager.cpp msgid "" @@ -7212,10 +7230,14 @@ msgid "" "Incompatible with older hardware\n" "Not recommended for web games" msgstr "" +"Mayor calidad visual\n" +"Todas las caracterÃsticas disponibles\n" +"Incompatible con hardware antiguo\n" +"No recomendado para juegos web" #: editor/project_manager.cpp msgid "OpenGL ES 2.0" -msgstr "" +msgstr "OpenGL ES 2.0" #: editor/project_manager.cpp msgid "" @@ -7224,10 +7246,16 @@ msgid "" "Works on most hardware\n" "Recommended for web games" msgstr "" +"Baja calidad visual\n" +"Algunas caracterÃsticas no disponibles\n" +"Funciona en la mayorÃa de hardware\n" +"Recomendado para juegos web" #: editor/project_manager.cpp msgid "Renderer can be changed later, but scenes may need to be adjusted." msgstr "" +"El renderizador se puede cambiar más tarde, pero es posible que las escenas " +"deban ajustarse." #: editor/project_manager.cpp msgid "Unnamed Project" @@ -7243,6 +7271,28 @@ msgstr "¿Seguro que quieres abrir más de un proyecto?" #: editor/project_manager.cpp msgid "" +"The following project settings file does not specify the version of Godot " +"through which it was created.\n" +"\n" +"%s\n" +"\n" +"If you proceed with opening it, it will be converted to Godot's current " +"configuration file format.\n" +"Warning: You will not be able to open the project with previous versions of " +"the engine anymore." +msgstr "" +"El siguiente archivo de configuración del proyecto no especifica la versión " +"de Godot con la que fue creado.\n" +"\n" +"%s\n" +"\n" +"Si procedes a abrirlo, se convertirá al formato de archivo de configuración " +"actual de Godot.\n" +"Advertencia: Ya no podrá abrir el proyecto con versiones anteriores del " +"motor." + +#: editor/project_manager.cpp +msgid "" "The following project settings file was generated by an older engine " "version, and needs to be converted for this version:\n" "\n" @@ -7959,10 +8009,12 @@ msgstr "Duplicar nodo(s)" #: editor/scene_tree_dock.cpp msgid "Can't reparent nodes in inherited scenes, order of nodes can't change." msgstr "" +"No se pueden reparar los nodos en las escenas heredadas, el orden de los " +"nodos no puede cambiar." #: editor/scene_tree_dock.cpp msgid "Node must belong to the edited scene to become root." -msgstr "" +msgstr "El nodo debe pertenecer a la escena editada para convertirse en raÃz." #: editor/scene_tree_dock.cpp msgid "Instantiated scenes can't become root" @@ -8034,7 +8086,7 @@ msgstr "¡No se puede operar sobre los nodos heredados por la escena actual!" #: editor/scene_tree_dock.cpp msgid "Attach Script" -msgstr "Añadir script" +msgstr "Añadir Script" #: editor/scene_tree_dock.cpp msgid "Remove Node(s)" @@ -8778,10 +8830,6 @@ msgid "Build Project" msgstr "Compilar proyecto" #: modules/mono/editor/mono_bottom_panel.cpp -msgid "Warnings" -msgstr "Advertencias" - -#: modules/mono/editor/mono_bottom_panel.cpp msgid "View log" msgstr "Ver registro" @@ -8807,7 +8855,7 @@ msgstr "Calculando tamaño de cuadrÃcula..." #: modules/recast/navigation_mesh_generator.cpp msgid "Creating heightfield..." -msgstr "Creando heightfield..." +msgstr "Creando campo de alturas..." #: modules/recast/navigation_mesh_generator.cpp msgid "Marking walkable triangles..." @@ -8831,7 +8879,7 @@ msgstr "Creando contornos..." #: modules/recast/navigation_mesh_generator.cpp msgid "Creating polymesh..." -msgstr "Crear polymesh..." +msgstr "Creando polymesh..." #: modules/recast/navigation_mesh_generator.cpp msgid "Converting to native navigation mesh..." @@ -9137,7 +9185,7 @@ msgstr "¡El objeto base no es un nodo!" #: modules/visual_script/visual_script_func_nodes.cpp msgid "Path does not lead Node!" -msgstr "¡La ruta no apunta a un nodo!" +msgstr "¡La ruta no apunta a un Nodo!" #: modules/visual_script/visual_script_func_nodes.cpp msgid "Invalid index property name '%s' in node %s." @@ -9187,11 +9235,11 @@ msgstr "Establecer %s" #: platform/android/export/export.cpp msgid "Package name is missing." -msgstr "" +msgstr "Nombre de paquete faltante." #: platform/android/export/export.cpp msgid "Package segments must be of non-zero length." -msgstr "" +msgstr "Los segmentos del paquete deben ser de largo no nulo." #: platform/android/export/export.cpp msgid "The character '%s' is not allowed in Android application package names." @@ -9201,11 +9249,12 @@ msgstr "" #: platform/android/export/export.cpp msgid "A digit cannot be the first character in a package segment." -msgstr "" +msgstr "Un dÃgito no puede ser el primer carácter en un segmento de paquete." #: platform/android/export/export.cpp msgid "The character '%s' cannot be the first character in a package segment." msgstr "" +"El carácter '%s' no puede ser el primer carácter en un segmento de paquete." #: platform/android/export/export.cpp msgid "The package must have at least one '.' separator." @@ -9221,16 +9270,15 @@ msgstr "OpenJDK jarsigner no configurado en Ajustes del Editor." #: platform/android/export/export.cpp msgid "Debug keystore not configured in the Editor Settings nor in the preset." -msgstr "" +msgstr "Keystore debug no configurada en Ajustes del Editor ni en el preset." #: platform/android/export/export.cpp msgid "Invalid public key for APK expansion." msgstr "Clave pública inválida para la expansión de APK." #: platform/android/export/export.cpp -#, fuzzy msgid "Invalid package name:" -msgstr "El nombre de clase no es correcto" +msgstr "Nombre de paquete inválido:" #: platform/iphone/export/export.cpp msgid "Identifier is missing." @@ -9238,21 +9286,23 @@ msgstr "Identificador no encontrado." #: platform/iphone/export/export.cpp msgid "Identifier segments must be of non-zero length." -msgstr "" +msgstr "Los segmentos de un identificador deben ser de largo no nulo." #: platform/iphone/export/export.cpp -#, fuzzy msgid "The character '%s' is not allowed in Identifier." -msgstr "El nombre no es un identificador válido:" +msgstr "El carácter '%s' no esta permitido como identificador." #: platform/iphone/export/export.cpp msgid "A digit cannot be the first character in a Identifier segment." msgstr "" +"Un dÃgito no puede ser el primer carácter en un segmento Identificador." #: platform/iphone/export/export.cpp msgid "" "The character '%s' cannot be the first character in a Identifier segment." msgstr "" +"El carácter '%s' no puede ser el primer carácter en un segmento " +"Identificador." #: platform/iphone/export/export.cpp msgid "The Identifier must have at least one '.' separator." @@ -9264,13 +9314,12 @@ msgstr "" "App Store Team ID no especificado - no se puede configurar el proyecto." #: platform/iphone/export/export.cpp -#, fuzzy msgid "Invalid Identifier:" -msgstr "El nombre no es un identificador válido:" +msgstr "Identificador inválido:" #: platform/iphone/export/export.cpp msgid "Required icon is not specified in the preset." -msgstr "" +msgstr "El icono requerido no está especificado en el preset." #: platform/javascript/export/export.cpp msgid "Run in Browser" @@ -9305,65 +9354,61 @@ msgid "Using default boot splash image." msgstr "Usando la imagen de carga por defecto." #: platform/uwp/export/export.cpp -#, fuzzy msgid "Invalid package unique name." -msgstr "El nombre no es correcto." +msgstr "Nombre único de paquete inválido." #: platform/uwp/export/export.cpp -#, fuzzy msgid "Invalid product GUID." -msgstr "Tamaño de tipografÃa incorrecto." +msgstr "GUID de producto inválido." #: platform/uwp/export/export.cpp -#, fuzzy msgid "Invalid publisher GUID." -msgstr "Ruta base incorrecta" +msgstr "GUID de publisher inválido." #: platform/uwp/export/export.cpp -#, fuzzy msgid "Invalid background color." -msgstr "El origen personalizado de tipografÃa no es correcto." +msgstr "Color de fondo inválido." #: platform/uwp/export/export.cpp -#, fuzzy msgid "Invalid Store Logo image dimensions (should be 50x50)." -msgstr "El logo de la tienda no es del tamaño adecuado (debe ser de 50x50)." +msgstr "" +"Las dimensiones de la imagen para el Store Logo son inválidas (deberÃa ser " +"50x50)." #: platform/uwp/export/export.cpp -#, fuzzy msgid "Invalid square 44x44 logo image dimensions (should be 44x44)." msgstr "" -"El logo cuadrado de 44x44 no es del tamaño adecuado (debe ser de 44x44)." +"Las dimensiones de la imagen para el logo cuadrado de 44x44 son inválidas " +"(deberÃa ser 44x44)." #: platform/uwp/export/export.cpp -#, fuzzy msgid "Invalid square 71x71 logo image dimensions (should be 71x71)." msgstr "" -"El logo cuadrado de 71x71 no es del tamaño adecuado (debe ser de 71x71)." +"Las dimensiones de la imagen para el logo cuadrado de 71x71 son inválidas " +"(deberÃa ser 71x71)." #: platform/uwp/export/export.cpp -#, fuzzy msgid "Invalid square 150x150 logo image dimensions (should be 150x150)." msgstr "" -"El logo cuadrado de 150x150 no es del tamaño adecuado (debe ser de 150x150)." +"Las dimensiones de la imagen para el logo cuadrado de 150x150 son inválidas " +"(deberÃa ser 150x150)." #: platform/uwp/export/export.cpp -#, fuzzy msgid "Invalid square 310x310 logo image dimensions (should be 310x310)." msgstr "" -"El logo cuadrado de 310x310 no es del tamaño adecuado (debe ser de 310x310)." +"Las dimensiones de la imagen para el logo cuadrado de 310x310 son inválidas " +"(deberÃa ser 310x310)." #: platform/uwp/export/export.cpp -#, fuzzy msgid "Invalid wide 310x150 logo image dimensions (should be 310x150)." msgstr "" -"El logo ancho de 310x150 no es del tamaño adecuado (debe ser de 310x150)." +"Las dimensiones de la imagen para el logo ancho de 310x150 son inválidas " +"(deberÃa ser 310x150)." #: platform/uwp/export/export.cpp -#, fuzzy msgid "Invalid splash screen image dimensions (should be 620x300)." msgstr "" -"El tamaño de la imagen de arranque no es correcto (debe ser de 620x300)." +"Las dimensiones de la imagen del splash son inválidas (deberÃa ser 620x300)." #: scene/2d/animated_sprite.cpp msgid "" @@ -9477,6 +9522,17 @@ msgstr "" "En nodo ParallaxLayer solo funciona cuando esta posicionado como hijo de un " "nodo ParallaxBackground." +#: scene/2d/particles_2d.cpp +msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles2D node instead. You can use the \"Convert to " +"CPUParticles\" option for this purpose." +msgstr "" +"Las partÃculas basadas en la GPU no son compatibles con el controlador de " +"vÃdeo GLES2.\n" +"En su lugar, utiliza el nodo CPUParticles2D. Para ello puedes utilizar la " +"opción \"Convertir a CPUParticles\"." + #: scene/2d/particles_2d.cpp scene/3d/particles.cpp msgid "" "A material to process the particles is not assigned, so no behavior is " @@ -9668,6 +9724,17 @@ msgstr "" #: scene/3d/particles.cpp msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles node instead. You can use the \"Convert to CPUParticles" +"\" option for this purpose." +msgstr "" +"Las partÃculas basadas en la GPU no son compatibles con el controlador de " +"vÃdeo GLES2.\n" +"En su lugar, utiliza el nodo CPUParticles. Para ello puedes utilizar la " +"opción \"Convertir a CPUParticles\"." + +#: scene/3d/particles.cpp +msgid "" "Nothing is visible because meshes have not been assigned to draw passes." msgstr "" "Nada es visible porque las mallas no se han asignado a los pases de dibujo." @@ -9686,13 +9753,12 @@ msgstr "" "PathFollow solo funciona cuando está asignado como hijo de un nodo Path." #: scene/3d/path.cpp -#, fuzzy msgid "" "PathFollow ROTATION_ORIENTED requires \"Up Vector\" enabled in its parent " "Path's Curve resource." msgstr "" -"OrientedPathFollow requiere que \"Up Vector\" esté activo en el recurso " -"Curve de su Path padre." +"PathFollow ROTATION_ORIENTED requiere que \"Up Vector\" esté activo en el " +"recurso Curve de su Path padre." #: scene/3d/physics_body.cpp msgid "" @@ -9709,26 +9775,6 @@ msgid "Path property must point to a valid Spatial node to work." msgstr "" "La propiedad Path debe apuntar a un nodo Spatial válido para funcionar." -#: scene/3d/scenario_fx.cpp -msgid "WorldEnvironment needs an Environment resource." -msgstr "WorldEnvironment necesita un recurso Environment." - -#: scene/3d/scenario_fx.cpp -msgid "" -"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." -msgstr "" -"Solo se permite un WorldEnvironment por escena (o conjunto de escenas " -"instanciadas)." - -#: scene/3d/scenario_fx.cpp -msgid "" -"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " -"this environment's Background Mode to Canvas (for 2D scenes)." -msgstr "" -"Este WorldEnvironment está siendo ignorado. Agrega un nodo Camera (para " -"escenas 3D) o configura el Background Mode de este entorno en modo Canvas " -"(para escenas 2D)." - #: scene/3d/soft_body.cpp msgid "This body will be ignored until you set a mesh" msgstr "Este cuerpo sera ignorado hasta que le asignes un mesh" @@ -9759,6 +9805,26 @@ msgstr "" "VehicleWheel sirve para proporcionar un sistema de ruedas a un VehicleBody. " "Por favor, úselo como hijo de un VehicleBody." +#: scene/3d/world_environment.cpp +msgid "WorldEnvironment needs an Environment resource." +msgstr "WorldEnvironment necesita un recurso Environment." + +#: scene/3d/world_environment.cpp +msgid "" +"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." +msgstr "" +"Solo se permite un WorldEnvironment por escena (o conjunto de escenas " +"instanciadas)." + +#: scene/3d/world_environment.cpp +msgid "" +"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " +"this environment's Background Mode to Canvas (for 2D scenes)." +msgstr "" +"Este WorldEnvironment está siendo ignorado. Agrega un nodo Camera (para " +"escenas 3D) o configura el Background Mode de este entorno en modo Canvas " +"(para escenas 2D)." + #: scene/animation/animation_blend_tree.cpp msgid "On BlendTree node '%s', animation not found: '%s'" msgstr "En el nodo BlendTree '%s', no se encontró la animación: '%s'" @@ -9802,11 +9868,20 @@ msgid "This node has been deprecated. Use AnimationTree instead." msgstr "Este nodo ha quedado obsoleto. Usa AnimationTree en su lugar." #: scene/gui/color_picker.cpp +msgid "Pick a color from the screen." +msgstr "Selecciona un color de la pantalla." + +#: scene/gui/color_picker.cpp msgid "Raw Mode" msgstr "Modo Raw" #: scene/gui/color_picker.cpp -msgid "Add current color as a preset" +msgid "Switch between hexadecimal and code values." +msgstr "Cambiar entre valores hexadecimales y de código." + +#: scene/gui/color_picker.cpp +#, fuzzy +msgid "Add current color as a preset." msgstr "Añadir el color actual como predeterminado" #: scene/gui/dialogs.cpp @@ -9901,6 +9976,18 @@ msgstr "Asignación a uniform." msgid "Varyings can only be assigned in vertex function." msgstr "Solo se pueden asignar variaciones en funciones de vértice." +#~ msgid "Warnings:" +#~ msgstr "Advertencias:" + +#~ msgid "Font Size:" +#~ msgstr "Tamaño de la tipografÃa:" + +#~ msgid "Line:" +#~ msgstr "LÃnea:" + +#~ msgid "Col:" +#~ msgstr "Columna:" + #~ msgid "OrientedPathFollow only works when set as a child of a Path node." #~ msgstr "" #~ "OrientedPathFollow solo funciona cuando esta asignado como hijo de un " diff --git a/editor/translations/es_AR.po b/editor/translations/es_AR.po index 86f1e6a72d..cd6f0166ac 100644 --- a/editor/translations/es_AR.po +++ b/editor/translations/es_AR.po @@ -8,12 +8,13 @@ # Sebastian Silva <sebastian@sugarlabs.org>, 2016. # Jose Luis Bossio <joseluisbossio@gmail.com>, 2018. # Reynaldo Cruz <rcruz60@gmail.com>, 2018. -# Javier Ocampos <xavier.ocampos@gmail.com>, 2018. +# Javier Ocampos <xavier.ocampos@gmail.com>, 2018, 2019. +# Andrés S <andres.segovia.dev@gmail.com>, 2019. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2019-01-26 21:22+0000\n" +"PO-Revision-Date: 2019-02-18 08:54+0000\n" "Last-Translator: Lisandro Lorea <lisandrolorea@gmail.com>\n" "Language-Team: Spanish (Argentina) <https://hosted.weblate.org/projects/" "godot-engine/godot/es_AR/>\n" @@ -549,21 +550,14 @@ msgstr "Zoom Out" msgid "Reset Zoom" msgstr "Resetear el Zoom" -#: editor/code_editor.cpp -msgid "Warnings:" -msgstr "Advertencias:" - -#: editor/code_editor.cpp -msgid "Font Size:" -msgstr "Tamaño de TipografÃa:" - -#: editor/code_editor.cpp -msgid "Line:" -msgstr "Linea:" +#: editor/code_editor.cpp modules/mono/editor/mono_bottom_panel.cpp +msgid "Warnings" +msgstr "Advertencias" #: editor/code_editor.cpp -msgid "Col:" -msgstr "Col:" +#, fuzzy +msgid "Line and column numbers." +msgstr "Números de lÃnea y columna" #: editor/connections_dialog.cpp msgid "Method in target Node must be specified!" @@ -864,8 +858,8 @@ msgstr "Eliminar archivos seleccionados?" #: editor/dependency_editor.cpp editor/editor_audio_buses.cpp #: editor/editor_file_dialog.cpp editor/editor_node.cpp #: editor/filesystem_dock.cpp editor/plugins/item_list_editor_plugin.cpp -#: editor/project_export.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_dock.cpp +#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp +#: editor/project_settings_editor.cpp editor/scene_tree_dock.cpp msgid "Delete" msgstr "Eliminar" @@ -1121,8 +1115,9 @@ msgid "Add Bus" msgstr "Agregar Bus" #: editor/editor_audio_buses.cpp -msgid "Create a new Bus Layout." -msgstr "Crear un nuevo Layout Bus." +#, fuzzy +msgid "Add a new Audio Bus to this layout." +msgstr "Guardar Layout de Bus de Audio Como..." #: editor/editor_audio_buses.cpp editor/editor_properties.cpp #: editor/plugins/animation_player_editor_plugin.cpp editor/property_editor.cpp @@ -1150,6 +1145,10 @@ msgstr "Cargar Valores por Defecto" msgid "Load the default Bus Layout." msgstr "Cargar el Bus Layout predeterminado." +#: editor/editor_audio_buses.cpp +msgid "Create a new Bus Layout." +msgstr "Crear un nuevo Layout Bus." + #: editor/editor_autoload_settings.cpp msgid "Invalid name." msgstr "Nombre inválido." @@ -2406,7 +2405,8 @@ msgid "Save & Restart" msgstr "Guardar y Reiniciar" #: editor/editor_node.cpp -msgid "Spins when the editor window repaints!" +#, fuzzy +msgid "Spins when the editor window redraws." msgstr "Gira cuando la ventana del editor repinta!" #: editor/editor_node.cpp @@ -3334,17 +3334,20 @@ msgstr "Reimportar" #: editor/import_dock.cpp msgid "Save scenes, re-import and restart" -msgstr "" +msgstr "Guardar escenas, reimportar y reiniciar" #: editor/import_dock.cpp -#, fuzzy msgid "Changing the type of an imported file requires editor restart." -msgstr "Cambiar el driver de video requiere reiniciar el editor." +msgstr "" +"Para cambiar el tipo de un archivo importado es necesario reiniciar el " +"editor." #: editor/import_dock.cpp msgid "" "WARNING: Assets exist that use this resource, they may stop loading properly." msgstr "" +"ADVERTENCIA: Existen elementos que utilizan este recurso, podrÃan dejar de " +"cargar correctamente." #: editor/inspector_dock.cpp msgid "Failed to load resource." @@ -3469,22 +3472,6 @@ msgid "Create Polygon" msgstr "Crear PolÃgono" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Edit Polygon" -msgstr "Editar PolÃgono" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Insert Point" -msgstr "Insertar Punto" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Edit Polygon (Remove Point)" -msgstr "Editar PolÃgono (Remover Punto)" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Remove Polygon And Point" -msgstr "Remover PolÃgono y Punto" - -#: editor/plugins/abstract_polygon_2d_editor.cpp #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp msgid "Create points." @@ -3505,6 +3492,22 @@ msgstr "" msgid "Erase points." msgstr "Borrar puntos." +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Edit Polygon" +msgstr "Editar PolÃgono" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Insert Point" +msgstr "Insertar Punto" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Edit Polygon (Remove Point)" +msgstr "Editar PolÃgono (Remover Punto)" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Remove Polygon And Point" +msgstr "Remover PolÃgono y Punto" + #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #: editor/plugins/animation_player_editor_plugin.cpp @@ -4311,6 +4314,18 @@ msgid "Move CanvasItem" msgstr "Mover CanvasItem" #: editor/plugins/canvas_item_editor_plugin.cpp +msgid "Presets for the anchors and margins values of a Control node." +msgstr "Presets para los valores de anclajes y márgenes de un nodo Control." + +#: editor/plugins/canvas_item_editor_plugin.cpp +msgid "" +"Children of containers have their anchors and margins values overridden by " +"their parent." +msgstr "" +"Los hijos de contenedores tienen su anclas y margenes determinados por sus " +"padres." + +#: editor/plugins/canvas_item_editor_plugin.cpp msgid "Anchors only" msgstr "Solo anclas" @@ -4497,7 +4512,7 @@ msgstr "Restablecer Huesos Personalizados" #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp msgid "View" -msgstr "Ver" +msgstr "Vista" #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/polygon_2d_editor_plugin.cpp @@ -5218,6 +5233,12 @@ msgid "Create UV Map" msgstr "Crear Mapa UV" #: editor/plugins/polygon_2d_editor_plugin.cpp +msgid "" +"Polygon 2D has internal vertices, so it can no longer be edited in the " +"viewport." +msgstr "" + +#: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Create Polygon & UV" msgstr "Crear PolÃgono y UV" @@ -5894,15 +5915,15 @@ msgstr "Ver Transformación en Plano." #: editor/plugins/spatial_editor_plugin.cpp msgid "Scaling: " -msgstr "Escalado: " +msgstr "Escalando: " #: editor/plugins/spatial_editor_plugin.cpp msgid "Translating: " -msgstr "Traducciones: " +msgstr "Trasladando: " #: editor/plugins/spatial_editor_plugin.cpp msgid "Rotating %s degrees." -msgstr "Torando %s grados." +msgstr "Rotando %s grados." #: editor/plugins/spatial_editor_plugin.cpp msgid "Keying is disabled (no key inserted)." @@ -6116,7 +6137,7 @@ msgstr "Modo Rotar (E)" #: editor/plugins/spatial_editor_plugin.cpp msgid "Scale Mode (R)" -msgstr "Modo de Escalado (R)" +msgstr "Modo Escalar (R)" #: editor/plugins/spatial_editor_plugin.cpp msgid "Local Coords" @@ -6204,7 +6225,7 @@ msgstr "Ajustar objeto al suelo" #: editor/plugins/spatial_editor_plugin.cpp msgid "Transform Dialog..." -msgstr "Dialogo de Transformación..." +msgstr "Cuadro de diálogo de Transform..." #: editor/plugins/spatial_editor_plugin.cpp msgid "1 Viewport" @@ -6308,7 +6329,7 @@ msgid "Post" msgstr "Post" #: editor/plugins/spatial_editor_plugin.cpp -msgid "Name-less gizmo" +msgid "Nameless gizmo" msgstr "Gizmo sin nombre" #: editor/plugins/sprite_editor_plugin.cpp @@ -6384,8 +6405,12 @@ msgid "(empty)" msgstr "(vacÃo)" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animations" -msgstr "Animaciones" +msgid "Animations:" +msgstr "Animaciones:" + +#: editor/plugins/sprite_frames_editor_plugin.cpp +msgid "New Animation" +msgstr "Nueva Animación" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed (FPS):" @@ -6396,8 +6421,8 @@ msgid "Loop" msgstr "Loop" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animation Frames" -msgstr "Cuadros de Animación" +msgid "Animation Frames:" +msgstr "Fotogramas de animación:" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Insert Empty (Before)" @@ -7152,11 +7177,11 @@ msgstr "Examinar" #: editor/project_manager.cpp msgid "Renderer:" -msgstr "" +msgstr "Renderizador:" #: editor/project_manager.cpp msgid "OpenGL ES 3.0" -msgstr "" +msgstr "OpenGL ES 3.0" #: editor/project_manager.cpp msgid "" @@ -7165,10 +7190,14 @@ msgid "" "Incompatible with older hardware\n" "Not recommended for web games" msgstr "" +"Mayor calidad visual\n" +"Todas las caracterÃsticas disponibles\n" +"Incompatible con hardware antiguo\n" +"No recomendado para juegos web" #: editor/project_manager.cpp msgid "OpenGL ES 2.0" -msgstr "" +msgstr "OpenGL ES 2.0" #: editor/project_manager.cpp msgid "" @@ -7177,10 +7206,16 @@ msgid "" "Works on most hardware\n" "Recommended for web games" msgstr "" +"Baja calidad visual\n" +"Algunas caracterÃsticas no disponibles\n" +"Funciona en la mayorÃa de hardware\n" +"Recomendado para juegos web" #: editor/project_manager.cpp msgid "Renderer can be changed later, but scenes may need to be adjusted." msgstr "" +"El renderizador se puede cambiar luego, pero es posible que sea necesario " +"ajustar las escenas." #: editor/project_manager.cpp msgid "Unnamed Project" @@ -7196,6 +7231,28 @@ msgstr "¿Estás seguro/a que quieres abrir más de un proyecto?" #: editor/project_manager.cpp msgid "" +"The following project settings file does not specify the version of Godot " +"through which it was created.\n" +"\n" +"%s\n" +"\n" +"If you proceed with opening it, it will be converted to Godot's current " +"configuration file format.\n" +"Warning: You will not be able to open the project with previous versions of " +"the engine anymore." +msgstr "" +"El siguiente archivo de configuración del proyecto no especifica la versión " +"de Godot con la que fue creado.\n" +"\n" +"%s\n" +"\n" +"Si procedés a abrirlo, sera convertido al formato actual de configuración de " +"Godot. \n" +"Advertencia: Ya no vas a poder volver a abrir el proyecto con versiones " +"anteriores del motor." + +#: editor/project_manager.cpp +msgid "" "The following project settings file was generated by an older engine " "version, and needs to be converted for this version:\n" "\n" @@ -7912,6 +7969,8 @@ msgstr "Duplicar Nodo(s)" #: editor/scene_tree_dock.cpp msgid "Can't reparent nodes in inherited scenes, order of nodes can't change." msgstr "" +"No se puede reemparentar nodos en escenas heredadas, el orden de nodos no " +"puede cambiar." #: editor/scene_tree_dock.cpp msgid "Node must belong to the edited scene to become root." @@ -8731,10 +8790,6 @@ msgid "Build Project" msgstr "Construir Proyecto" #: modules/mono/editor/mono_bottom_panel.cpp -msgid "Warnings" -msgstr "Advertencias" - -#: modules/mono/editor/mono_bottom_panel.cpp msgid "View log" msgstr "Ver registro" @@ -9311,7 +9366,7 @@ msgstr "" #: platform/uwp/export/export.cpp msgid "Invalid splash screen image dimensions (should be 620x300)." -msgstr "Dimensiones de la imagen del splash inválidas (deberÃa ser 620x400)." +msgstr "Dimensiones de la imagen del splash inválidas (deberÃa ser 620x300)." #: scene/2d/animated_sprite.cpp msgid "" @@ -9422,6 +9477,17 @@ msgstr "" "El nodo ParallaxLayer sólo funciona cuando está seteado como hijo de un nodo " "ParallaxBackground." +#: scene/2d/particles_2d.cpp +msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles2D node instead. You can use the \"Convert to " +"CPUParticles\" option for this purpose." +msgstr "" +"Las partÃculas basadas en la GPU no son compatibles con el controlador de " +"vÃdeo GLES2.\n" +"En su lugar, utiliza el nodo CPUParticles2D. Para ello podés utilizar la " +"opción \"Convertir a CPUParticles\"." + #: scene/2d/particles_2d.cpp scene/3d/particles.cpp msgid "" "A material to process the particles is not assigned, so no behavior is " @@ -9611,6 +9677,17 @@ msgstr "" #: scene/3d/particles.cpp msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles node instead. You can use the \"Convert to CPUParticles" +"\" option for this purpose." +msgstr "" +"Las partÃculas basadas en la GPU no son compatibles con el controlador de " +"vÃdeo GLES2.\n" +"En su lugar, utilizá el nodo CPUParticles. Para ello podés utilizar la " +"opción \"Convertir a CPUParticles\"." + +#: scene/3d/particles.cpp +msgid "" "Nothing is visible because meshes have not been assigned to draw passes." msgstr "Nada visible ya que no se asigno pasadas de dibujado a los meshes." @@ -9650,26 +9727,6 @@ msgid "Path property must point to a valid Spatial node to work." msgstr "" "La propiedad Path debe apuntar a un nodo Spatial valido para funcionar." -#: scene/3d/scenario_fx.cpp -msgid "WorldEnvironment needs an Environment resource." -msgstr "WorldEnvironment necesita un recurso Environment." - -#: scene/3d/scenario_fx.cpp -msgid "" -"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." -msgstr "" -"Solo se permite un WorldEnvironment por escena (o conjunto de escenas " -"instanciadas)." - -#: scene/3d/scenario_fx.cpp -msgid "" -"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " -"this environment's Background Mode to Canvas (for 2D scenes)." -msgstr "" -"Este WorldEnvironment esta siendo ignorado. Agregá un nodo Camera (para " -"escenas 3D) o configurá el Background Mode de este entorno en modo Canvas " -"(para escenas 2D)." - #: scene/3d/soft_body.cpp msgid "This body will be ignored until you set a mesh" msgstr "Este cuerpo sera ignorado hasta que le asignes un mesh" @@ -9700,6 +9757,26 @@ msgstr "" "VehicleWheel sirve para proveer un sistema de ruedas a VehicleBody. Por " "favor usálo como hijo de VehicleBody." +#: scene/3d/world_environment.cpp +msgid "WorldEnvironment needs an Environment resource." +msgstr "WorldEnvironment necesita un recurso Environment." + +#: scene/3d/world_environment.cpp +msgid "" +"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." +msgstr "" +"Solo se permite un WorldEnvironment por escena (o conjunto de escenas " +"instanciadas)." + +#: scene/3d/world_environment.cpp +msgid "" +"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " +"this environment's Background Mode to Canvas (for 2D scenes)." +msgstr "" +"Este WorldEnvironment esta siendo ignorado. Agregá un nodo Camera (para " +"escenas 3D) o configurá el Background Mode de este entorno en modo Canvas " +"(para escenas 2D)." + #: scene/animation/animation_blend_tree.cpp msgid "On BlendTree node '%s', animation not found: '%s'" msgstr "En el nodo BlendTree '%s', no se encontró la animación: '%s'" @@ -9743,11 +9820,20 @@ msgid "This node has been deprecated. Use AnimationTree instead." msgstr "Este nodo ha sido deprecado. Usá AnimationTree." #: scene/gui/color_picker.cpp +msgid "Pick a color from the screen." +msgstr "Elegir un color de la pantalla." + +#: scene/gui/color_picker.cpp msgid "Raw Mode" msgstr "Modo Raw" #: scene/gui/color_picker.cpp -msgid "Add current color as a preset" +msgid "Switch between hexadecimal and code values." +msgstr "Cambiar entre valores hexadecimales y de código." + +#: scene/gui/color_picker.cpp +#, fuzzy +msgid "Add current color as a preset." msgstr "Agregar color actual como preset" #: scene/gui/dialogs.cpp @@ -9842,6 +9928,18 @@ msgstr "Asignación a uniform." msgid "Varyings can only be assigned in vertex function." msgstr "Solo se pueden asignar variaciones en funciones de vértice." +#~ msgid "Warnings:" +#~ msgstr "Advertencias:" + +#~ msgid "Font Size:" +#~ msgstr "Tamaño de TipografÃa:" + +#~ msgid "Line:" +#~ msgstr "Linea:" + +#~ msgid "Col:" +#~ msgstr "Col:" + #~ msgid "OrientedPathFollow only works when set as a child of a Path node." #~ msgstr "" #~ "OrientedPathFollow solo funciona cuando esta asignado como hijo de un " diff --git a/editor/translations/et.po b/editor/translations/et.po index 948c2861b7..0b1cef1a31 100644 --- a/editor/translations/et.po +++ b/editor/translations/et.po @@ -526,20 +526,12 @@ msgstr "" msgid "Reset Zoom" msgstr "" -#: editor/code_editor.cpp -msgid "Warnings:" -msgstr "" - -#: editor/code_editor.cpp -msgid "Font Size:" -msgstr "" - -#: editor/code_editor.cpp -msgid "Line:" +#: editor/code_editor.cpp modules/mono/editor/mono_bottom_panel.cpp +msgid "Warnings" msgstr "" #: editor/code_editor.cpp -msgid "Col:" +msgid "Line and column numbers." msgstr "" #: editor/connections_dialog.cpp @@ -833,8 +825,8 @@ msgstr "" #: editor/dependency_editor.cpp editor/editor_audio_buses.cpp #: editor/editor_file_dialog.cpp editor/editor_node.cpp #: editor/filesystem_dock.cpp editor/plugins/item_list_editor_plugin.cpp -#: editor/project_export.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_dock.cpp +#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp +#: editor/project_settings_editor.cpp editor/scene_tree_dock.cpp msgid "Delete" msgstr "" @@ -1086,7 +1078,7 @@ msgid "Add Bus" msgstr "" #: editor/editor_audio_buses.cpp -msgid "Create a new Bus Layout." +msgid "Add a new Audio Bus to this layout." msgstr "" #: editor/editor_audio_buses.cpp editor/editor_properties.cpp @@ -1115,6 +1107,10 @@ msgstr "" msgid "Load the default Bus Layout." msgstr "" +#: editor/editor_audio_buses.cpp +msgid "Create a new Bus Layout." +msgstr "" + #: editor/editor_autoload_settings.cpp msgid "Invalid name." msgstr "" @@ -2285,7 +2281,7 @@ msgid "Save & Restart" msgstr "" #: editor/editor_node.cpp -msgid "Spins when the editor window repaints!" +msgid "Spins when the editor window redraws." msgstr "" #: editor/editor_node.cpp @@ -3323,37 +3319,37 @@ msgid "Create Polygon" msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Edit Polygon" +#: editor/plugins/animation_blend_space_1d_editor.cpp +#: editor/plugins/animation_blend_space_2d_editor.cpp +msgid "Create points." msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Insert Point" +msgid "" +"Edit points.\n" +"LMB: Move Point\n" +"RMB: Erase Point" msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Edit Polygon (Remove Point)" +#: editor/plugins/animation_blend_space_1d_editor.cpp +msgid "Erase points." msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Remove Polygon And Point" +msgid "Edit Polygon" msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -#: editor/plugins/animation_blend_space_1d_editor.cpp -#: editor/plugins/animation_blend_space_2d_editor.cpp -msgid "Create points." +msgid "Insert Point" msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "" -"Edit points.\n" -"LMB: Move Point\n" -"RMB: Erase Point" +msgid "Edit Polygon (Remove Point)" msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -#: editor/plugins/animation_blend_space_1d_editor.cpp -msgid "Erase points." +msgid "Remove Polygon And Point" msgstr "" #: editor/plugins/animation_blend_space_1d_editor.cpp @@ -4136,6 +4132,16 @@ msgid "Move CanvasItem" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp +msgid "Presets for the anchors and margins values of a Control node." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp +msgid "" +"Children of containers have their anchors and margins values overridden by " +"their parent." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp msgid "Anchors only" msgstr "" @@ -5031,6 +5037,12 @@ msgid "Create UV Map" msgstr "" #: editor/plugins/polygon_2d_editor_plugin.cpp +msgid "" +"Polygon 2D has internal vertices, so it can no longer be edited in the " +"viewport." +msgstr "" + +#: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Create Polygon & UV" msgstr "" @@ -6112,7 +6124,7 @@ msgid "Post" msgstr "" #: editor/plugins/spatial_editor_plugin.cpp -msgid "Name-less gizmo" +msgid "Nameless gizmo" msgstr "" #: editor/plugins/sprite_editor_plugin.cpp @@ -6188,7 +6200,11 @@ msgid "(empty)" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animations" +msgid "Animations:" +msgstr "" + +#: editor/plugins/sprite_frames_editor_plugin.cpp +msgid "New Animation" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp @@ -6200,7 +6216,7 @@ msgid "Loop" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animation Frames" +msgid "Animation Frames:" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp @@ -6976,6 +6992,19 @@ msgstr "" #: editor/project_manager.cpp msgid "" +"The following project settings file does not specify the version of Godot " +"through which it was created.\n" +"\n" +"%s\n" +"\n" +"If you proceed with opening it, it will be converted to Godot's current " +"configuration file format.\n" +"Warning: You will not be able to open the project with previous versions of " +"the engine anymore." +msgstr "" + +#: editor/project_manager.cpp +msgid "" "The following project settings file was generated by an older engine " "version, and needs to be converted for this version:\n" "\n" @@ -8452,10 +8481,6 @@ msgid "Build Project" msgstr "" #: modules/mono/editor/mono_bottom_panel.cpp -msgid "Warnings" -msgstr "" - -#: modules/mono/editor/mono_bottom_panel.cpp msgid "View log" msgstr "" @@ -9081,6 +9106,13 @@ msgid "" "ParallaxLayer node only works when set as child of a ParallaxBackground node." msgstr "" +#: scene/2d/particles_2d.cpp +msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles2D node instead. You can use the \"Convert to " +"CPUParticles\" option for this purpose." +msgstr "" + #: scene/2d/particles_2d.cpp scene/3d/particles.cpp msgid "" "A material to process the particles is not assigned, so no behavior is " @@ -9236,6 +9268,13 @@ msgstr "" #: scene/3d/particles.cpp msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles node instead. You can use the \"Convert to CPUParticles" +"\" option for this purpose." +msgstr "" + +#: scene/3d/particles.cpp +msgid "" "Nothing is visible because meshes have not been assigned to draw passes." msgstr "" @@ -9266,21 +9305,6 @@ msgstr "" msgid "Path property must point to a valid Spatial node to work." msgstr "" -#: scene/3d/scenario_fx.cpp -msgid "WorldEnvironment needs an Environment resource." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " -"this environment's Background Mode to Canvas (for 2D scenes)." -msgstr "" - #: scene/3d/soft_body.cpp msgid "This body will be ignored until you set a mesh" msgstr "" @@ -9304,6 +9328,21 @@ msgid "" "it as a child of a VehicleBody." msgstr "" +#: scene/3d/world_environment.cpp +msgid "WorldEnvironment needs an Environment resource." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " +"this environment's Background Mode to Canvas (for 2D scenes)." +msgstr "" + #: scene/animation/animation_blend_tree.cpp msgid "On BlendTree node '%s', animation not found: '%s'" msgstr "" @@ -9345,11 +9384,19 @@ msgid "This node has been deprecated. Use AnimationTree instead." msgstr "" #: scene/gui/color_picker.cpp +msgid "Pick a color from the screen." +msgstr "" + +#: scene/gui/color_picker.cpp msgid "Raw Mode" msgstr "" #: scene/gui/color_picker.cpp -msgid "Add current color as a preset" +msgid "Switch between hexadecimal and code values." +msgstr "" + +#: scene/gui/color_picker.cpp +msgid "Add current color as a preset." msgstr "" #: scene/gui/dialogs.cpp diff --git a/editor/translations/fa.po b/editor/translations/fa.po index 0eec8c6d9d..a0a64fe6d8 100644 --- a/editor/translations/fa.po +++ b/editor/translations/fa.po @@ -560,22 +560,14 @@ msgstr "بزرگنمایی کمتر" msgid "Reset Zoom" msgstr "بازنشانی بزرگنمایی" -#: editor/code_editor.cpp -msgid "Warnings:" +#: editor/code_editor.cpp modules/mono/editor/mono_bottom_panel.cpp +msgid "Warnings" msgstr "" #: editor/code_editor.cpp -msgid "Font Size:" +msgid "Line and column numbers." msgstr "" -#: editor/code_editor.cpp -msgid "Line:" -msgstr "خط:" - -#: editor/code_editor.cpp -msgid "Col:" -msgstr "ستون:" - #: editor/connections_dialog.cpp msgid "Method in target Node must be specified!" msgstr "متد در گره مقصد باید مشخص شده باشد!" @@ -883,8 +875,8 @@ msgstr "آیا پرونده‌های انتخاب شده ØØ°Ù شود؟" #: editor/dependency_editor.cpp editor/editor_audio_buses.cpp #: editor/editor_file_dialog.cpp editor/editor_node.cpp #: editor/filesystem_dock.cpp editor/plugins/item_list_editor_plugin.cpp -#: editor/project_export.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_dock.cpp +#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp +#: editor/project_settings_editor.cpp editor/scene_tree_dock.cpp msgid "Delete" msgstr "ØØ°Ù Ú©Ù†" @@ -1143,7 +1135,7 @@ msgid "Add Bus" msgstr "" #: editor/editor_audio_buses.cpp -msgid "Create a new Bus Layout." +msgid "Add a new Audio Bus to this layout." msgstr "" #: editor/editor_audio_buses.cpp editor/editor_properties.cpp @@ -1172,6 +1164,10 @@ msgstr "بارگیری پیش ÙØ±Ø¶" msgid "Load the default Bus Layout." msgstr "" +#: editor/editor_audio_buses.cpp +msgid "Create a new Bus Layout." +msgstr "" + #: editor/editor_autoload_settings.cpp msgid "Invalid name." msgstr "نام نامعتبر." @@ -2378,7 +2374,7 @@ msgid "Save & Restart" msgstr "ذخیره Ùˆ خروج" #: editor/editor_node.cpp -msgid "Spins when the editor window repaints!" +msgid "Spins when the editor window redraws." msgstr "" #: editor/editor_node.cpp @@ -3463,24 +3459,6 @@ msgid "Create Polygon" msgstr "انتخاب شده را تغییر مقیاس بده" #: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Edit Polygon" -msgstr "ویرایش سیگنال" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Insert Point" -msgstr "" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Edit Polygon (Remove Point)" -msgstr "" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Remove Polygon And Point" -msgstr "برداشتن نقش" - -#: editor/plugins/abstract_polygon_2d_editor.cpp #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #, fuzzy @@ -3500,6 +3478,24 @@ msgstr "" msgid "Erase points." msgstr "Ú©Ùندی در آغاز" +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Edit Polygon" +msgstr "ویرایش سیگنال" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Insert Point" +msgstr "" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Edit Polygon (Remove Point)" +msgstr "" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Remove Polygon And Point" +msgstr "برداشتن نقش" + #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #: editor/plugins/animation_player_editor_plugin.cpp @@ -4310,6 +4306,16 @@ msgid "Move CanvasItem" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp +msgid "Presets for the anchors and margins values of a Control node." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp +msgid "" +"Children of containers have their anchors and margins values overridden by " +"their parent." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp msgid "Anchors only" msgstr "" @@ -5224,6 +5230,12 @@ msgid "Create UV Map" msgstr "" #: editor/plugins/polygon_2d_editor_plugin.cpp +msgid "" +"Polygon 2D has internal vertices, so it can no longer be edited in the " +"viewport." +msgstr "" + +#: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Create Polygon & UV" msgstr "" @@ -6361,7 +6373,7 @@ msgid "Post" msgstr "" #: editor/plugins/spatial_editor_plugin.cpp -msgid "Name-less gizmo" +msgid "Nameless gizmo" msgstr "" #: editor/plugins/sprite_editor_plugin.cpp @@ -6442,8 +6454,14 @@ msgid "(empty)" msgstr "(خالی)" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animations" -msgstr "" +#, fuzzy +msgid "Animations:" +msgstr "گره انیمیشن" + +#: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "New Animation" +msgstr "تغییر نام انیمیشن" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed (FPS):" @@ -6454,8 +6472,9 @@ msgid "Loop" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animation Frames" -msgstr "" +#, fuzzy +msgid "Animation Frames:" +msgstr "گره انیمیشن" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Insert Empty (Before)" @@ -7286,6 +7305,19 @@ msgstr "" #: editor/project_manager.cpp msgid "" +"The following project settings file does not specify the version of Godot " +"through which it was created.\n" +"\n" +"%s\n" +"\n" +"If you proceed with opening it, it will be converted to Godot's current " +"configuration file format.\n" +"Warning: You will not be able to open the project with previous versions of " +"the engine anymore." +msgstr "" + +#: editor/project_manager.cpp +msgid "" "The following project settings file was generated by an older engine " "version, and needs to be converted for this version:\n" "\n" @@ -8832,10 +8864,6 @@ msgid "Build Project" msgstr "پروژه" #: modules/mono/editor/mono_bottom_panel.cpp -msgid "Warnings" -msgstr "" - -#: modules/mono/editor/mono_bottom_panel.cpp #, fuzzy msgid "View log" msgstr "نمایش پرونده ها" @@ -9525,6 +9553,13 @@ msgstr "" "گره ParallaxLayer تنها در زمانی Ú©Ù‡ به عنوان ÙØ±Ø²Ù†Ø¯ یک گره ParallaxBackground " "تنظیم شود کار می‌کند." +#: scene/2d/particles_2d.cpp +msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles2D node instead. You can use the \"Convert to " +"CPUParticles\" option for this purpose." +msgstr "" + #: scene/2d/particles_2d.cpp scene/3d/particles.cpp msgid "" "A material to process the particles is not assigned, so no behavior is " @@ -9696,6 +9731,13 @@ msgstr "" #: scene/3d/particles.cpp msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles node instead. You can use the \"Convert to CPUParticles" +"\" option for this purpose." +msgstr "" + +#: scene/3d/particles.cpp +msgid "" "Nothing is visible because meshes have not been assigned to draw passes." msgstr "" @@ -9730,23 +9772,6 @@ msgstr "" msgid "Path property must point to a valid Spatial node to work." msgstr "دارایی Path باید به یک گره Particles2D معتبر اشاره کند تا کار کند." -#: scene/3d/scenario_fx.cpp -msgid "WorldEnvironment needs an Environment resource." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." -msgstr "" -"Ùقط یک WorldEnvironment در هر صØÙ†Ù‡ (یا مجموعه ای از صØÙ†Ù‡ های نمونه‌گذاری شده) " -"مجاز است." - -#: scene/3d/scenario_fx.cpp -msgid "" -"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " -"this environment's Background Mode to Canvas (for 2D scenes)." -msgstr "" - #: scene/3d/soft_body.cpp msgid "This body will be ignored until you set a mesh" msgstr "" @@ -9772,6 +9797,23 @@ msgid "" "it as a child of a VehicleBody." msgstr "" +#: scene/3d/world_environment.cpp +msgid "WorldEnvironment needs an Environment resource." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." +msgstr "" +"Ùقط یک WorldEnvironment در هر صØÙ†Ù‡ (یا مجموعه ای از صØÙ†Ù‡ های نمونه‌گذاری شده) " +"مجاز است." + +#: scene/3d/world_environment.cpp +msgid "" +"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " +"this environment's Background Mode to Canvas (for 2D scenes)." +msgstr "" + #: scene/animation/animation_blend_tree.cpp msgid "On BlendTree node '%s', animation not found: '%s'" msgstr "" @@ -9818,11 +9860,19 @@ msgid "This node has been deprecated. Use AnimationTree instead." msgstr "" #: scene/gui/color_picker.cpp +msgid "Pick a color from the screen." +msgstr "" + +#: scene/gui/color_picker.cpp msgid "Raw Mode" msgstr "" #: scene/gui/color_picker.cpp -msgid "Add current color as a preset" +msgid "Switch between hexadecimal and code values." +msgstr "" + +#: scene/gui/color_picker.cpp +msgid "Add current color as a preset." msgstr "" #: scene/gui/dialogs.cpp @@ -9913,6 +9963,12 @@ msgstr "" msgid "Varyings can only be assigned in vertex function." msgstr "" +#~ msgid "Line:" +#~ msgstr "خط:" + +#~ msgid "Col:" +#~ msgstr "ستون:" + #, fuzzy #~ msgid "OrientedPathFollow only works when set as a child of a Path node." #~ msgstr "" diff --git a/editor/translations/fi.po b/editor/translations/fi.po index 094baf8c80..392fd0e2ad 100644 --- a/editor/translations/fi.po +++ b/editor/translations/fi.po @@ -13,7 +13,7 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2019-01-26 21:22+0000\n" +"PO-Revision-Date: 2019-02-13 07:10+0000\n" "Last-Translator: Tapani Niemi <tapani.niemi@kapsi.fi>\n" "Language-Team: Finnish <https://hosted.weblate.org/projects/godot-engine/" "godot/fi/>\n" @@ -543,21 +543,14 @@ msgstr "Loitonna" msgid "Reset Zoom" msgstr "Palauta oletuslähennystaso" -#: editor/code_editor.cpp -msgid "Warnings:" -msgstr "Varoitukset:" - -#: editor/code_editor.cpp -msgid "Font Size:" -msgstr "Fontin koko:" - -#: editor/code_editor.cpp -msgid "Line:" -msgstr "Rivi:" +#: editor/code_editor.cpp modules/mono/editor/mono_bottom_panel.cpp +msgid "Warnings" +msgstr "Varoitukset" #: editor/code_editor.cpp -msgid "Col:" -msgstr "Sarake:" +#, fuzzy +msgid "Line and column numbers." +msgstr "Rivi- ja sarakenumerot" #: editor/connections_dialog.cpp msgid "Method in target Node must be specified!" @@ -859,8 +852,8 @@ msgstr "Poista valitut tiedostot?" #: editor/dependency_editor.cpp editor/editor_audio_buses.cpp #: editor/editor_file_dialog.cpp editor/editor_node.cpp #: editor/filesystem_dock.cpp editor/plugins/item_list_editor_plugin.cpp -#: editor/project_export.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_dock.cpp +#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp +#: editor/project_settings_editor.cpp editor/scene_tree_dock.cpp msgid "Delete" msgstr "Poista" @@ -1116,8 +1109,9 @@ msgid "Add Bus" msgstr "Lisää väylä" #: editor/editor_audio_buses.cpp -msgid "Create a new Bus Layout." -msgstr "Luo uusi ääniväylän asettelu." +#, fuzzy +msgid "Add a new Audio Bus to this layout." +msgstr "Tallenna ääniväylän asettelu nimellä..." #: editor/editor_audio_buses.cpp editor/editor_properties.cpp #: editor/plugins/animation_player_editor_plugin.cpp editor/property_editor.cpp @@ -1145,6 +1139,10 @@ msgstr "Lataa oletus" msgid "Load the default Bus Layout." msgstr "Lataa väylän oletusasettelu." +#: editor/editor_audio_buses.cpp +msgid "Create a new Bus Layout." +msgstr "Luo uusi ääniväylän asettelu." + #: editor/editor_autoload_settings.cpp msgid "Invalid name." msgstr "Virheellinen nimi." @@ -2383,7 +2381,8 @@ msgid "Save & Restart" msgstr "Tallenna & käynnistä uudelleen" #: editor/editor_node.cpp -msgid "Spins when the editor window repaints!" +#, fuzzy +msgid "Spins when the editor window redraws." msgstr "Pyörii kun editorin ikkuna päivittyy!" #: editor/editor_node.cpp @@ -3310,17 +3309,20 @@ msgstr "Tuo uudelleen" #: editor/import_dock.cpp msgid "Save scenes, re-import and restart" -msgstr "" +msgstr "Tallenna skenet, tuo uudelleen ja käynnistä uudelleen" #: editor/import_dock.cpp -#, fuzzy msgid "Changing the type of an imported file requires editor restart." -msgstr "Näyttöajurin vaihtaminen edellyttää editorin uudelleenkäynnistystä." +msgstr "" +"Tuodun tiedoston tyypin muuttaminen edellyttää editorin " +"uudelleenkäynnistystä." #: editor/import_dock.cpp msgid "" "WARNING: Assets exist that use this resource, they may stop loading properly." msgstr "" +"VAROITUS: Tällä resurssilla on sitä käyttäviä assetteja, ne voivat lakata " +"latautumasta kunnolla." #: editor/inspector_dock.cpp msgid "Failed to load resource." @@ -3445,22 +3447,6 @@ msgid "Create Polygon" msgstr "Luo polygoni" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Edit Polygon" -msgstr "Muokkaa polygonia" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Insert Point" -msgstr "Lisää piste" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Edit Polygon (Remove Point)" -msgstr "Muokkaa polygonia (poista piste)" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Remove Polygon And Point" -msgstr "Poista polygoni ja piste" - -#: editor/plugins/abstract_polygon_2d_editor.cpp #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp msgid "Create points." @@ -3481,6 +3467,22 @@ msgstr "" msgid "Erase points." msgstr "Pyyhi pisteitä." +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Edit Polygon" +msgstr "Muokkaa polygonia" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Insert Point" +msgstr "Lisää piste" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Edit Polygon (Remove Point)" +msgstr "Muokkaa polygonia (poista piste)" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Remove Polygon And Point" +msgstr "Poista polygoni ja piste" + #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #: editor/plugins/animation_player_editor_plugin.cpp @@ -4283,6 +4285,18 @@ msgid "Move CanvasItem" msgstr "Siirrä CanvasItemiä" #: editor/plugins/canvas_item_editor_plugin.cpp +msgid "Presets for the anchors and margins values of a Control node." +msgstr "Control solmun ankkureiden ja marginaalien arvojen esiasetukset." + +#: editor/plugins/canvas_item_editor_plugin.cpp +msgid "" +"Children of containers have their anchors and margins values overridden by " +"their parent." +msgstr "" +"Säilön alisolmujen ankkurien ja marginaalien arvot ylikirjoittuvat niiden " +"isäntäsolmun toimesta." + +#: editor/plugins/canvas_item_editor_plugin.cpp msgid "Anchors only" msgstr "Vain ankkurit" @@ -5191,6 +5205,12 @@ msgid "Create UV Map" msgstr "Luo UV kartta" #: editor/plugins/polygon_2d_editor_plugin.cpp +msgid "" +"Polygon 2D has internal vertices, so it can no longer be edited in the " +"viewport." +msgstr "" + +#: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Create Polygon & UV" msgstr "Luo polygoni ja UV" @@ -6229,7 +6249,7 @@ msgstr "Siirrettäessä:" #: editor/plugins/spatial_editor_plugin.cpp msgid "Rotate Snap (deg.):" -msgstr "Käännettäessä (aste):" +msgstr "Käännettäessä (asteina):" #: editor/plugins/spatial_editor_plugin.cpp msgid "Scale Snap (%):" @@ -6241,7 +6261,7 @@ msgstr "Näyttöruudun asetukset" #: editor/plugins/spatial_editor_plugin.cpp msgid "Perspective FOV (deg.):" -msgstr "Näkökentän perspektiivi (ast.):" +msgstr "Näkökentän perspektiivi (asteina):" #: editor/plugins/spatial_editor_plugin.cpp msgid "View Z-Near:" @@ -6261,7 +6281,7 @@ msgstr "Siirrä:" #: editor/plugins/spatial_editor_plugin.cpp msgid "Rotate (deg.):" -msgstr "Kierrä (ast.):" +msgstr "Kierrä (asteina):" #: editor/plugins/spatial_editor_plugin.cpp msgid "Scale (ratio):" @@ -6280,7 +6300,7 @@ msgid "Post" msgstr "Jälki" #: editor/plugins/spatial_editor_plugin.cpp -msgid "Name-less gizmo" +msgid "Nameless gizmo" msgstr "Nimetön muokkain" #: editor/plugins/sprite_editor_plugin.cpp @@ -6356,8 +6376,12 @@ msgid "(empty)" msgstr "(tyhjä)" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animations" -msgstr "Animaatiot" +msgid "Animations:" +msgstr "Animaatiot:" + +#: editor/plugins/sprite_frames_editor_plugin.cpp +msgid "New Animation" +msgstr "Uusi animaatio" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed (FPS):" @@ -6368,8 +6392,8 @@ msgid "Loop" msgstr "Toista" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animation Frames" -msgstr "Animaatioruudut" +msgid "Animation Frames:" +msgstr "Animaatioruudut:" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Insert Empty (Before)" @@ -7123,11 +7147,11 @@ msgstr "Selaa" #: editor/project_manager.cpp msgid "Renderer:" -msgstr "" +msgstr "Renderöijä:" #: editor/project_manager.cpp msgid "OpenGL ES 3.0" -msgstr "" +msgstr "OpenGL ES 3.0" #: editor/project_manager.cpp msgid "" @@ -7136,10 +7160,14 @@ msgid "" "Incompatible with older hardware\n" "Not recommended for web games" msgstr "" +"Korkea visuaalinen laatu\n" +"Kaikki ominaisuudet käytettävissä\n" +"Epäyhteensopiva vanhojen laitteiden kanssa\n" +"Ei suositeltu web-peleille" #: editor/project_manager.cpp msgid "OpenGL ES 2.0" -msgstr "" +msgstr "OpenGL ES 2.0" #: editor/project_manager.cpp msgid "" @@ -7148,10 +7176,15 @@ msgid "" "Works on most hardware\n" "Recommended for web games" msgstr "" +"Matalampi visuaalinen laatu\n" +"Jotkin ominaisuudet eivät ole käytettävissä\n" +"Toimii useimmilla laitteilla\n" +"Suositeltu web-peleille" #: editor/project_manager.cpp msgid "Renderer can be changed later, but scenes may need to be adjusted." msgstr "" +"Renderöijä voidaan vaihtaa myöhemmin, mutta skenejä voi joutua mukauttamaan." #: editor/project_manager.cpp msgid "Unnamed Project" @@ -7167,6 +7200,27 @@ msgstr "Haluatko varmasti avata useamman kuin yhden projektin?" #: editor/project_manager.cpp msgid "" +"The following project settings file does not specify the version of Godot " +"through which it was created.\n" +"\n" +"%s\n" +"\n" +"If you proceed with opening it, it will be converted to Godot's current " +"configuration file format.\n" +"Warning: You will not be able to open the project with previous versions of " +"the engine anymore." +msgstr "" +"Seuraava projektin asetustiedosto ei määrittele Godotin versiota, jolla se " +"on luotu.\n" +"\n" +"%s\n" +"\n" +"Jos haluat jatkaa sen avaamista, se muunnetaan nykyiseen Godotin " +"asetustiedostomuotoon.\n" +"Varoitus: et voi avata projektia tämän jälkeen enää vanhemmilla versioilla." + +#: editor/project_manager.cpp +msgid "" "The following project settings file was generated by an older engine " "version, and needs to be converted for this version:\n" "\n" @@ -7876,6 +7930,8 @@ msgstr "Kahdenna solmu(t)" #: editor/scene_tree_dock.cpp msgid "Can't reparent nodes in inherited scenes, order of nodes can't change." msgstr "" +"Perittyjen skenejen solmujen isäntää ei voi vaihtaa, solmujen järjestys ei " +"voi muuttua." #: editor/scene_tree_dock.cpp msgid "Node must belong to the edited scene to become root." @@ -8696,10 +8752,6 @@ msgid "Build Project" msgstr "Käännä projekti" #: modules/mono/editor/mono_bottom_panel.cpp -msgid "Warnings" -msgstr "Varoitukset" - -#: modules/mono/editor/mono_bottom_panel.cpp msgid "View log" msgstr "Näytä loki" @@ -9369,6 +9421,16 @@ msgstr "" "ParallaxLayer solmu toimii ainoastaan, jos se on ParallaxBackground solmun " "alla." +#: scene/2d/particles_2d.cpp +msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles2D node instead. You can use the \"Convert to " +"CPUParticles\" option for this purpose." +msgstr "" +"GPU-pohjaiset partikkelit eivät ole tuettuja GLES2 näyttöajurilla.\n" +"Käytä sen sijaan CPUParticles2D solmua. Voit käyttää \"Muunna " +"CPUPartikkeleiksi\" toimintoa tähän tarkoitukseen." + #: scene/2d/particles_2d.cpp scene/3d/particles.cpp msgid "" "A material to process the particles is not assigned, so no behavior is " @@ -9560,6 +9622,16 @@ msgstr "" #: scene/3d/particles.cpp msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles node instead. You can use the \"Convert to CPUParticles" +"\" option for this purpose." +msgstr "" +"GPU-pohjaiset partikkelit eivät ole tuettuja GLES2 näyttöajurilla.\n" +"Käytä sen sijaan CPUParticles solmua. Voit käyttää \"Muunna CPUPartikkeleiksi" +"\" toimintoa tähän tarkoitukseen." + +#: scene/3d/particles.cpp +msgid "" "Nothing is visible because meshes have not been assigned to draw passes." msgstr "" "Mitään ei näy, koska mesheille ei ole asetettu piirtopyyhkäisyjä (draw " @@ -9599,26 +9671,6 @@ msgstr "" msgid "Path property must point to a valid Spatial node to work." msgstr "Polkuominaisuuden täytyy osoittaa Spatial solmuun toimiakseen." -#: scene/3d/scenario_fx.cpp -msgid "WorldEnvironment needs an Environment resource." -msgstr "WorldEnvironment tarvitsee Environment resurssin." - -#: scene/3d/scenario_fx.cpp -msgid "" -"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." -msgstr "" -"Vain yksi WorldEnvironment on sallittu per skene (tai per skeneilmentymien " -"joukko)." - -#: scene/3d/scenario_fx.cpp -msgid "" -"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " -"this environment's Background Mode to Canvas (for 2D scenes)." -msgstr "" -"Tämä WorldEnvironment jätetään huomioimatta. Lisää joko Camera (3D-" -"skeneille) tai aseta tälle ympäristölle Background Mode asetukseksi Canvas " -"(2D-skeneille)." - #: scene/3d/soft_body.cpp msgid "This body will be ignored until you set a mesh" msgstr "Tämä kappale sivuutetaan, kunnes asetat meshin" @@ -9648,6 +9700,26 @@ msgstr "" "VehicleWheel solmu tarjoaa rengasjärjestelmän VehicleBody solmulle. Ole hyvä " "ja käytä sitä VehicleBody solmun alla." +#: scene/3d/world_environment.cpp +msgid "WorldEnvironment needs an Environment resource." +msgstr "WorldEnvironment tarvitsee Environment resurssin." + +#: scene/3d/world_environment.cpp +msgid "" +"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." +msgstr "" +"Vain yksi WorldEnvironment on sallittu per skene (tai per skeneilmentymien " +"joukko)." + +#: scene/3d/world_environment.cpp +msgid "" +"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " +"this environment's Background Mode to Canvas (for 2D scenes)." +msgstr "" +"Tämä WorldEnvironment jätetään huomioimatta. Lisää joko Camera (3D-" +"skeneille) tai aseta tälle ympäristölle Background Mode asetukseksi Canvas " +"(2D-skeneille)." + #: scene/animation/animation_blend_tree.cpp msgid "On BlendTree node '%s', animation not found: '%s'" msgstr "BlendTree solmusta '%' ei löytynyt animaatiota: '%s'" @@ -9691,11 +9763,20 @@ msgstr "" "Tämä solmu on poistettu käytöstä. Käytä sen sijaan AnimationTree solmua." #: scene/gui/color_picker.cpp +msgid "Pick a color from the screen." +msgstr "Valitse väri ruudulta." + +#: scene/gui/color_picker.cpp msgid "Raw Mode" msgstr "Raakatila" #: scene/gui/color_picker.cpp -msgid "Add current color as a preset" +msgid "Switch between hexadecimal and code values." +msgstr "Vaihda heksadesimaali- ja koodiarvojen välillä." + +#: scene/gui/color_picker.cpp +#, fuzzy +msgid "Add current color as a preset." msgstr "Lisää nykyinen väri esiasetukseksi" #: scene/gui/dialogs.cpp @@ -9790,6 +9871,18 @@ msgstr "Sijoitus uniformille." msgid "Varyings can only be assigned in vertex function." msgstr "Varying tyypin voi sijoittaa vain vertex-funktiossa." +#~ msgid "Warnings:" +#~ msgstr "Varoitukset:" + +#~ msgid "Font Size:" +#~ msgstr "Fontin koko:" + +#~ msgid "Line:" +#~ msgstr "Rivi:" + +#~ msgid "Col:" +#~ msgstr "Sarake:" + #~ msgid "OrientedPathFollow only works when set as a child of a Path node." #~ msgstr "" #~ "OrientedPathFollow toimii ainoastaan ollessaan asetettuna Path solmun " diff --git a/editor/translations/fr.po b/editor/translations/fr.po index 3827c3f40b..4fe762d13b 100644 --- a/editor/translations/fr.po +++ b/editor/translations/fr.po @@ -57,8 +57,8 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2019-01-26 21:22+0000\n" -"Last-Translator: Rémi Bintein <reminus5@hotmail.fr>\n" +"PO-Revision-Date: 2019-02-18 08:54+0000\n" +"Last-Translator: Caye Pierre <pierrecaye@laposte.net>\n" "Language-Team: French <https://hosted.weblate.org/projects/godot-engine/" "godot/fr/>\n" "Language: fr\n" @@ -598,21 +598,14 @@ msgstr "Dézoomer" msgid "Reset Zoom" msgstr "Réinitialiser le zoom" -#: editor/code_editor.cpp -msgid "Warnings:" -msgstr "Avertissements :" - -#: editor/code_editor.cpp -msgid "Font Size:" -msgstr "Taille de police :" - -#: editor/code_editor.cpp -msgid "Line:" -msgstr "Ligne :" +#: editor/code_editor.cpp modules/mono/editor/mono_bottom_panel.cpp +msgid "Warnings" +msgstr "Avertissements" #: editor/code_editor.cpp -msgid "Col:" -msgstr "Colonne :" +#, fuzzy +msgid "Line and column numbers." +msgstr "Numéros de ligne et de colonne" #: editor/connections_dialog.cpp msgid "Method in target Node must be specified!" @@ -915,8 +908,8 @@ msgstr "Supprimer les fichiers sélectionnés ?" #: editor/dependency_editor.cpp editor/editor_audio_buses.cpp #: editor/editor_file_dialog.cpp editor/editor_node.cpp #: editor/filesystem_dock.cpp editor/plugins/item_list_editor_plugin.cpp -#: editor/project_export.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_dock.cpp +#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp +#: editor/project_settings_editor.cpp editor/scene_tree_dock.cpp msgid "Delete" msgstr "Supprimer" @@ -1172,8 +1165,9 @@ msgid "Add Bus" msgstr "Ajouter un bus" #: editor/editor_audio_buses.cpp -msgid "Create a new Bus Layout." -msgstr "Créer une nouvel agencement de tranport." +#, fuzzy +msgid "Add a new Audio Bus to this layout." +msgstr "Enregistrer la disposition des bus audio sous…" #: editor/editor_audio_buses.cpp editor/editor_properties.cpp #: editor/plugins/animation_player_editor_plugin.cpp editor/property_editor.cpp @@ -1201,6 +1195,10 @@ msgstr "Charger défaut" msgid "Load the default Bus Layout." msgstr "Charger l'agencement de transport par défaut." +#: editor/editor_audio_buses.cpp +msgid "Create a new Bus Layout." +msgstr "Créer une nouvel agencement de tranport." + #: editor/editor_autoload_settings.cpp msgid "Invalid name." msgstr "Nom invalide." @@ -2463,7 +2461,8 @@ msgid "Save & Restart" msgstr "Enregistrer et Redémarrer" #: editor/editor_node.cpp -msgid "Spins when the editor window repaints!" +#, fuzzy +msgid "Spins when the editor window redraws." msgstr "Tourne lorsque la fenêtre de l'éditeur est repainte !" #: editor/editor_node.cpp @@ -3396,17 +3395,19 @@ msgstr "Ré-importer" #: editor/import_dock.cpp msgid "Save scenes, re-import and restart" -msgstr "" +msgstr "Sauvegarde des scènes, réimportation et redémarrage" #: editor/import_dock.cpp -#, fuzzy msgid "Changing the type of an imported file requires editor restart." -msgstr "Changer le pilote vidéo nécessite le redémarrage de l'éditeur." +msgstr "" +"Changer le type d'un fichier importé nécessite un redémarrage de l'éditeur." #: editor/import_dock.cpp msgid "" "WARNING: Assets exist that use this resource, they may stop loading properly." msgstr "" +"AVERTISSEMENT : Il existe des éléments qui utilisent cette ressource, ils " +"pourraient cesser de charger correctement." #: editor/inspector_dock.cpp msgid "Failed to load resource." @@ -3531,22 +3532,6 @@ msgid "Create Polygon" msgstr "Créer un polygone" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Edit Polygon" -msgstr "Modifier le polygone" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Insert Point" -msgstr "Insérer un point" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Edit Polygon (Remove Point)" -msgstr "Modifier le polygone (supprimer un point)" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Remove Polygon And Point" -msgstr "Supprimer le polygone et le point" - -#: editor/plugins/abstract_polygon_2d_editor.cpp #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp msgid "Create points." @@ -3567,6 +3552,22 @@ msgstr "" msgid "Erase points." msgstr "Effacer des points." +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Edit Polygon" +msgstr "Modifier le polygone" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Insert Point" +msgstr "Insérer un point" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Edit Polygon (Remove Point)" +msgstr "Modifier le polygone (supprimer un point)" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Remove Polygon And Point" +msgstr "Supprimer le polygone et le point" + #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #: editor/plugins/animation_player_editor_plugin.cpp @@ -4377,6 +4378,18 @@ msgid "Move CanvasItem" msgstr "Déplacer l'élément de canevas" #: editor/plugins/canvas_item_editor_plugin.cpp +msgid "Presets for the anchors and margins values of a Control node." +msgstr "Préréglages pour les ancres et les marges d'un nÅ“ud Control." + +#: editor/plugins/canvas_item_editor_plugin.cpp +msgid "" +"Children of containers have their anchors and margins values overridden by " +"their parent." +msgstr "" +"Les nÅ“uds enfants de conteneurs ont leurs ancres et marges redéfinies par " +"leur parent." + +#: editor/plugins/canvas_item_editor_plugin.cpp msgid "Anchors only" msgstr "Uniquement les ancres" @@ -4682,7 +4695,7 @@ msgstr "Définir la poignée" #: editor/plugins/cpu_particles_editor_plugin.cpp msgid "CPUParticles" -msgstr "ParticulesCPU" +msgstr "CPUParticles" #: editor/plugins/cpu_particles_editor_plugin.cpp #: editor/plugins/particles_editor_plugin.cpp @@ -5051,7 +5064,7 @@ msgstr "Effacer Masque d'Émission" #: editor/plugins/particles_2d_editor_plugin.cpp #: editor/plugins/particles_editor_plugin.cpp msgid "Convert to CPUParticles" -msgstr "Convertir en ParticulesCPU" +msgstr "Convertir en CPUParticles" #: editor/plugins/particles_2d_editor_plugin.cpp #: editor/plugins/particles_editor_plugin.cpp @@ -5290,6 +5303,12 @@ msgid "Create UV Map" msgstr "Créer une carte UV" #: editor/plugins/polygon_2d_editor_plugin.cpp +msgid "" +"Polygon 2D has internal vertices, so it can no longer be edited in the " +"viewport." +msgstr "" + +#: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Create Polygon & UV" msgstr "Créer un polygone & UV" @@ -6381,7 +6400,7 @@ msgid "Post" msgstr "Post" #: editor/plugins/spatial_editor_plugin.cpp -msgid "Name-less gizmo" +msgid "Nameless gizmo" msgstr "Gadget sans nom" #: editor/plugins/sprite_editor_plugin.cpp @@ -6459,8 +6478,12 @@ msgid "(empty)" msgstr "(vide)" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animations" -msgstr "Animations" +msgid "Animations:" +msgstr "Animations :" + +#: editor/plugins/sprite_frames_editor_plugin.cpp +msgid "New Animation" +msgstr "Nouvelle animation" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed (FPS):" @@ -6471,8 +6494,8 @@ msgid "Loop" msgstr "Boucle" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animation Frames" -msgstr "Trames d'animation" +msgid "Animation Frames:" +msgstr "Trames d'animation :" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Insert Empty (Before)" @@ -7229,11 +7252,11 @@ msgstr "Parcourir" #: editor/project_manager.cpp msgid "Renderer:" -msgstr "" +msgstr "Moteur de rendu :" #: editor/project_manager.cpp msgid "OpenGL ES 3.0" -msgstr "" +msgstr "OpenGL ES 3.0" #: editor/project_manager.cpp msgid "" @@ -7242,10 +7265,14 @@ msgid "" "Incompatible with older hardware\n" "Not recommended for web games" msgstr "" +"Meilleure qualité visuelle\n" +"Toutes les fonctions disponibles\n" +"Incompatible avec du matériel plus ancien\n" +"Non recommandé pour les jeux web" #: editor/project_manager.cpp msgid "OpenGL ES 2.0" -msgstr "" +msgstr "OpenGL ES 2.0" #: editor/project_manager.cpp msgid "" @@ -7254,10 +7281,16 @@ msgid "" "Works on most hardware\n" "Recommended for web games" msgstr "" +"Qualité visuelle inférieure\n" +"Certaines fonctions ne sont pas disponibles\n" +"Fonctionne sur la plupart du matériel\n" +"Recommandé pour les jeux en ligne" #: editor/project_manager.cpp msgid "Renderer can be changed later, but scenes may need to be adjusted." msgstr "" +"Le rendu peut être modifié ultérieurement, mais les scènes peuvent avoir " +"besoin d'être ajustées." #: editor/project_manager.cpp msgid "Unnamed Project" @@ -7273,6 +7306,28 @@ msgstr "Voulez-vous vraiment ouvrir plus d'un projet à la fois ?" #: editor/project_manager.cpp msgid "" +"The following project settings file does not specify the version of Godot " +"through which it was created.\n" +"\n" +"%s\n" +"\n" +"If you proceed with opening it, it will be converted to Godot's current " +"configuration file format.\n" +"Warning: You will not be able to open the project with previous versions of " +"the engine anymore." +msgstr "" +"Le fichier de configuration de projet ci-dessous n'indique pas par quelle " +"version de Godot il a été généré.\n" +"\n" +"%s\n" +"\n" +"Si vous choisissez de l'ouvrir, il sera converti vers l'actuel format de " +"fichier de configuration de Godot.\n" +"Attention : Il ne sera plus possible d'ouvrir ce projet avec les précédentes " +"versions du moteur." + +#: editor/project_manager.cpp +msgid "" "The following project settings file was generated by an older engine " "version, and needs to be converted for this version:\n" "\n" @@ -7989,6 +8044,8 @@ msgstr "Dupliquer le(s) nÅ“ud(s)" #: editor/scene_tree_dock.cpp msgid "Can't reparent nodes in inherited scenes, order of nodes can't change." msgstr "" +"Impossible de reparenter les nÅ“uds dans les scènes héritées, l'ordre des " +"nÅ“uds ne peut pas changer." #: editor/scene_tree_dock.cpp msgid "Node must belong to the edited scene to become root." @@ -8386,7 +8443,7 @@ msgstr "Processus enfant connecté" #: editor/script_editor_debugger.cpp msgid "Copy Error" -msgstr "Erreurs de copie" +msgstr "Copier l'erreur" #: editor/script_editor_debugger.cpp msgid "Inspect Previous Instance" @@ -8809,10 +8866,6 @@ msgid "Build Project" msgstr "Compiler le projet" #: modules/mono/editor/mono_bottom_panel.cpp -msgid "Warnings" -msgstr "Avertissements" - -#: modules/mono/editor/mono_bottom_panel.cpp msgid "View log" msgstr "Voir les fichiers log" @@ -9255,7 +9308,6 @@ msgstr "" "OpenJDK jarsigner n'est pas configuré dans les paramètres de l'éditeur." #: platform/android/export/export.cpp -#, fuzzy msgid "Debug keystore not configured in the Editor Settings nor in the preset." msgstr "" "Debug keystore n'est pas configuré dans les paramètres de l'éditeur ni dans " @@ -9464,7 +9516,7 @@ msgid "" "\"Particles Animation\" enabled." msgstr "" "L'animation de CPUParticles2D a besoin d'un CanvasItemMaterial avec " -"\"Animation de Particules\" activé." +"\"Particles Animation\" activé." #: scene/2d/light_2d.cpp msgid "" @@ -9511,6 +9563,17 @@ msgstr "" "Le nÅ“ud ParallaxLayer ne fonctionne que s'il est défini en tant qu'enfant " "d'un nÅ“ud de type ParallaxBackground." +#: scene/2d/particles_2d.cpp +msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles2D node instead. You can use the \"Convert to " +"CPUParticles\" option for this purpose." +msgstr "" +"Les particules de type GPU ne sont pas supportées par le pilote graphique " +"GLES2.\n" +"Utilisez le nÅ“ud CPUParticles2D à la place. Vous pouvez utiliser l'option « " +"Convertir en CPUParticles » pour ce faire." + #: scene/2d/particles_2d.cpp scene/3d/particles.cpp msgid "" "A material to process the particles is not assigned, so no behavior is " @@ -9703,6 +9766,17 @@ msgstr "" #: scene/3d/particles.cpp msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles node instead. You can use the \"Convert to CPUParticles" +"\" option for this purpose." +msgstr "" +"Les particules de type GPU ne sont pas supportées par le pilote graphique " +"GLES2.\n" +"Utilisez le nÅ“ud CPUParticles à la place. Vous pouvez utiliser l'option « " +"Convertir en CPUParticles » pour ce faire." + +#: scene/3d/particles.cpp +msgid "" "Nothing is visible because meshes have not been assigned to draw passes." msgstr "" "Rien n'est visible car les maillages n'ont pas été assignés au tirage des " @@ -9745,26 +9819,6 @@ msgid "Path property must point to a valid Spatial node to work." msgstr "" "La propriété Path doit pointer vers un nÅ“ud Spatial valide pour fonctionner." -#: scene/3d/scenario_fx.cpp -msgid "WorldEnvironment needs an Environment resource." -msgstr "WorldEnvironment requiert une ressource de type Environment." - -#: scene/3d/scenario_fx.cpp -msgid "" -"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." -msgstr "" -"Seul un WorldEnvironnement ne peut être utilisé par scène (ou ensemble de " -"scènes instanciées)." - -#: scene/3d/scenario_fx.cpp -msgid "" -"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " -"this environment's Background Mode to Canvas (for 2D scenes)." -msgstr "" -"Ce WorldEnvironment est ignoré. Ajoutez une caméra (pour les scènes 3D) ou " -"définissez la propriété \"Background Mode\" de cet environnement sur \"Canvas" -"\" (pour les scènes 2D)." - #: scene/3d/soft_body.cpp msgid "This body will be ignored until you set a mesh" msgstr "Ce corps sera ignoré jusqu'à ce que vous définissiez un maillage" @@ -9795,6 +9849,26 @@ msgstr "" "VehicleWheel permet de fournir un système de roue à un VehicleBody. Merci de " "l'utiliser comme enfant d'un VehicleBody." +#: scene/3d/world_environment.cpp +msgid "WorldEnvironment needs an Environment resource." +msgstr "WorldEnvironment requiert une ressource de type Environment." + +#: scene/3d/world_environment.cpp +msgid "" +"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." +msgstr "" +"Seul un WorldEnvironnement ne peut être utilisé par scène (ou ensemble de " +"scènes instanciées)." + +#: scene/3d/world_environment.cpp +msgid "" +"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " +"this environment's Background Mode to Canvas (for 2D scenes)." +msgstr "" +"Ce WorldEnvironment est ignoré. Ajoutez une caméra (pour les scènes 3D) ou " +"définissez la propriété \"Background Mode\" de cet environnement sur \"Canvas" +"\" (pour les scènes 2D)." + #: scene/animation/animation_blend_tree.cpp msgid "On BlendTree node '%s', animation not found: '%s'" msgstr "Sur le nÅ“ud BlendTree '%s', animation introuvable : '%s'" @@ -9839,11 +9913,20 @@ msgid "This node has been deprecated. Use AnimationTree instead." msgstr "Ce nÅ“ud est désormais déprécié. Utilisez AnimationTree à la place." #: scene/gui/color_picker.cpp +msgid "Pick a color from the screen." +msgstr "Échantillonner une couleur depuis l'écran." + +#: scene/gui/color_picker.cpp msgid "Raw Mode" msgstr "Mode brut" #: scene/gui/color_picker.cpp -msgid "Add current color as a preset" +msgid "Switch between hexadecimal and code values." +msgstr "Alterner entre les valeurs hexadécimales ou brutes." + +#: scene/gui/color_picker.cpp +#, fuzzy +msgid "Add current color as a preset." msgstr "Ajouter la couleur courante comme pré-réglage" #: scene/gui/dialogs.cpp @@ -9940,6 +10023,18 @@ msgstr "Affectation à l'uniforme." msgid "Varyings can only be assigned in vertex function." msgstr "Les variations ne peuvent être affectées que dans la fonction vertex." +#~ msgid "Warnings:" +#~ msgstr "Avertissements :" + +#~ msgid "Font Size:" +#~ msgstr "Taille de police :" + +#~ msgid "Line:" +#~ msgstr "Ligne :" + +#~ msgid "Col:" +#~ msgstr "Colonne :" + #~ msgid "OrientedPathFollow only works when set as a child of a Path node." #~ msgstr "" #~ "Le nÅ“ud OrientedPathFollow ne fonctionne que s'il est défini en tant " diff --git a/editor/translations/he.po b/editor/translations/he.po index 09d368d4e3..7257d9c753 100644 --- a/editor/translations/he.po +++ b/editor/translations/he.po @@ -561,23 +561,13 @@ msgstr "להתרחק" msgid "Reset Zoom" msgstr "×יפוס התקריב" -#: editor/code_editor.cpp -#, fuzzy -msgid "Warnings:" +#: editor/code_editor.cpp modules/mono/editor/mono_bottom_panel.cpp +msgid "Warnings" msgstr "×זהרות" #: editor/code_editor.cpp -#, fuzzy -msgid "Font Size:" -msgstr "מבט קדמי" - -#: editor/code_editor.cpp -msgid "Line:" -msgstr "שורה:" - -#: editor/code_editor.cpp -msgid "Col:" -msgstr "עמודה:" +msgid "Line and column numbers." +msgstr "" #: editor/connections_dialog.cpp msgid "Method in target Node must be specified!" @@ -876,8 +866,8 @@ msgstr "למחוק ×ת ×”×§×‘×¦×™× ×”× ×‘×—×¨×™×?" #: editor/dependency_editor.cpp editor/editor_audio_buses.cpp #: editor/editor_file_dialog.cpp editor/editor_node.cpp #: editor/filesystem_dock.cpp editor/plugins/item_list_editor_plugin.cpp -#: editor/project_export.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_dock.cpp +#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp +#: editor/project_settings_editor.cpp editor/scene_tree_dock.cpp msgid "Delete" msgstr "למחוק" @@ -1130,8 +1120,9 @@ msgid "Add Bus" msgstr "הוספת ×פיק" #: editor/editor_audio_buses.cpp -msgid "Create a new Bus Layout." -msgstr "יצירת פריסת ××¤×™×§×™× ×—×“×©×”." +#, fuzzy +msgid "Add a new Audio Bus to this layout." +msgstr "שמירת פריסת ×פיקי השמע בתור…" #: editor/editor_audio_buses.cpp editor/editor_properties.cpp #: editor/plugins/animation_player_editor_plugin.cpp editor/property_editor.cpp @@ -1159,6 +1150,10 @@ msgstr "×˜×¢×™× ×ª בררת המחדל" msgid "Load the default Bus Layout." msgstr "×˜×¢×™× ×ª בררת המחדל של פריסת ×פיקי השמע." +#: editor/editor_audio_buses.cpp +msgid "Create a new Bus Layout." +msgstr "יצירת פריסת ××¤×™×§×™× ×—×“×©×”." + #: editor/editor_autoload_settings.cpp msgid "Invalid name." msgstr "×©× ×©×’×•×™." @@ -2367,7 +2362,8 @@ msgid "Save & Restart" msgstr "לשמור ולצ×ת" #: editor/editor_node.cpp -msgid "Spins when the editor window repaints!" +#, fuzzy +msgid "Spins when the editor window redraws." msgstr "מסתובב ×›×שר חלון העורך מצויר מחדש!" #: editor/editor_node.cpp @@ -3447,25 +3443,6 @@ msgid "Create Polygon" msgstr "יצירת מצולע" #: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Edit Polygon" -msgstr "עריכת מצולע" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Insert Point" -msgstr "הוספת × ×§×•×“×”" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Edit Polygon (Remove Point)" -msgstr "עריכת מצולע (הסרת × ×§×•×“×”)" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Remove Polygon And Point" -msgstr "הסרת מצולע ×•× ×§×•×“×”" - -#: editor/plugins/abstract_polygon_2d_editor.cpp #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #, fuzzy @@ -3485,6 +3462,25 @@ msgstr "" msgid "Erase points." msgstr "מחיקת × ×§×•×“×•×ª" +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Edit Polygon" +msgstr "עריכת מצולע" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Insert Point" +msgstr "הוספת × ×§×•×“×”" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Edit Polygon (Remove Point)" +msgstr "עריכת מצולע (הסרת × ×§×•×“×”)" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Remove Polygon And Point" +msgstr "הסרת מצולע ×•× ×§×•×“×”" + #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #: editor/plugins/animation_player_editor_plugin.cpp @@ -4287,6 +4283,16 @@ msgid "Move CanvasItem" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp +msgid "Presets for the anchors and margins values of a Control node." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp +msgid "" +"Children of containers have their anchors and margins values overridden by " +"their parent." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp msgid "Anchors only" msgstr "" @@ -5194,6 +5200,12 @@ msgid "Create UV Map" msgstr "" #: editor/plugins/polygon_2d_editor_plugin.cpp +msgid "" +"Polygon 2D has internal vertices, so it can no longer be edited in the " +"viewport." +msgstr "" + +#: editor/plugins/polygon_2d_editor_plugin.cpp #, fuzzy msgid "Create Polygon & UV" msgstr "יצירת מצולע" @@ -6322,7 +6334,7 @@ msgid "Post" msgstr "" #: editor/plugins/spatial_editor_plugin.cpp -msgid "Name-less gizmo" +msgid "Nameless gizmo" msgstr "" #: editor/plugins/sprite_editor_plugin.cpp @@ -6402,10 +6414,16 @@ msgid "(empty)" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animations" +#, fuzzy +msgid "Animations:" msgstr "×× ×™×ž×¦×™×•×ª" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "New Animation" +msgstr "×©× ×”× ×¤×©×” חדשה:" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed (FPS):" msgstr "מהירות (FPS):" @@ -6414,7 +6432,8 @@ msgid "Loop" msgstr "לול××”" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animation Frames" +#, fuzzy +msgid "Animation Frames:" msgstr "שקופיות ×”×”× ×¤×©×”" #: editor/plugins/sprite_frames_editor_plugin.cpp @@ -7227,6 +7246,19 @@ msgstr "" #: editor/project_manager.cpp msgid "" +"The following project settings file does not specify the version of Godot " +"through which it was created.\n" +"\n" +"%s\n" +"\n" +"If you proceed with opening it, it will be converted to Godot's current " +"configuration file format.\n" +"Warning: You will not be able to open the project with previous versions of " +"the engine anymore." +msgstr "" + +#: editor/project_manager.cpp +msgid "" "The following project settings file was generated by an older engine " "version, and needs to be converted for this version:\n" "\n" @@ -8734,10 +8766,6 @@ msgid "Build Project" msgstr "" #: modules/mono/editor/mono_bottom_panel.cpp -msgid "Warnings" -msgstr "×זהרות" - -#: modules/mono/editor/mono_bottom_panel.cpp msgid "View log" msgstr "" @@ -9374,6 +9402,13 @@ msgid "" msgstr "" "מפרק ParallaxLayer עובד רק ×›×שר ×”×•× ×ž×•×’×“×¨ כצ××¦× ×©×œ מפרק ParallaxBackground." +#: scene/2d/particles_2d.cpp +msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles2D node instead. You can use the \"Convert to " +"CPUParticles\" option for this purpose." +msgstr "" + #: scene/2d/particles_2d.cpp scene/3d/particles.cpp msgid "" "A material to process the particles is not assigned, so no behavior is " @@ -9529,6 +9564,13 @@ msgstr "" #: scene/3d/particles.cpp msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles node instead. You can use the \"Convert to CPUParticles" +"\" option for this purpose." +msgstr "" + +#: scene/3d/particles.cpp +msgid "" "Nothing is visible because meshes have not been assigned to draw passes." msgstr "" @@ -9560,21 +9602,6 @@ msgstr "" msgid "Path property must point to a valid Spatial node to work." msgstr "" -#: scene/3d/scenario_fx.cpp -msgid "WorldEnvironment needs an Environment resource." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " -"this environment's Background Mode to Canvas (for 2D scenes)." -msgstr "" - #: scene/3d/soft_body.cpp msgid "This body will be ignored until you set a mesh" msgstr "" @@ -9598,6 +9625,21 @@ msgid "" "it as a child of a VehicleBody." msgstr "" +#: scene/3d/world_environment.cpp +msgid "WorldEnvironment needs an Environment resource." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " +"this environment's Background Mode to Canvas (for 2D scenes)." +msgstr "" + #: scene/animation/animation_blend_tree.cpp msgid "On BlendTree node '%s', animation not found: '%s'" msgstr "" @@ -9641,11 +9683,20 @@ msgid "This node has been deprecated. Use AnimationTree instead." msgstr "" #: scene/gui/color_picker.cpp +msgid "Pick a color from the screen." +msgstr "" + +#: scene/gui/color_picker.cpp msgid "Raw Mode" msgstr "מצב גולמי" #: scene/gui/color_picker.cpp -msgid "Add current color as a preset" +msgid "Switch between hexadecimal and code values." +msgstr "" + +#: scene/gui/color_picker.cpp +#, fuzzy +msgid "Add current color as a preset." msgstr "הוספת הצבע ×”× ×•×›×—×™ כערכה" #: scene/gui/dialogs.cpp @@ -9730,6 +9781,20 @@ msgid "Varyings can only be assigned in vertex function." msgstr "" #, fuzzy +#~ msgid "Warnings:" +#~ msgstr "×זהרות" + +#, fuzzy +#~ msgid "Font Size:" +#~ msgstr "מבט קדמי" + +#~ msgid "Line:" +#~ msgstr "שורה:" + +#~ msgid "Col:" +#~ msgstr "עמודה:" + +#, fuzzy #~ msgid "OrientedPathFollow only works when set as a child of a Path node." #~ msgstr "PathFollow2D עובד רק ×›×שר ×”×•× ×ž×•×’×“×¨ כצ××¦× ×©×œ מפרק Path2D." diff --git a/editor/translations/hi.po b/editor/translations/hi.po index 687665d165..5aee390cc5 100644 --- a/editor/translations/hi.po +++ b/editor/translations/hi.po @@ -544,22 +544,14 @@ msgstr "छोटा करो" msgid "Reset Zoom" msgstr "रीसेट आकार" -#: editor/code_editor.cpp -msgid "Warnings:" +#: editor/code_editor.cpp modules/mono/editor/mono_bottom_panel.cpp +msgid "Warnings" msgstr "" #: editor/code_editor.cpp -msgid "Font Size:" +msgid "Line and column numbers." msgstr "" -#: editor/code_editor.cpp -msgid "Line:" -msgstr "रेखा:" - -#: editor/code_editor.cpp -msgid "Col:" -msgstr "सà¥à¤¤à¤‚à¤:" - #: editor/connections_dialog.cpp msgid "Method in target Node must be specified!" msgstr "लकà¥à¤·à¥à¤¯ नोड में विधि निरà¥à¤¦à¤¿à¤·à¥à¤Ÿ किया जाना चाहिà¤!" @@ -877,8 +869,8 @@ msgstr "चयनित फ़ाइलें हटाà¤à¤‚?" #: editor/dependency_editor.cpp editor/editor_audio_buses.cpp #: editor/editor_file_dialog.cpp editor/editor_node.cpp #: editor/filesystem_dock.cpp editor/plugins/item_list_editor_plugin.cpp -#: editor/project_export.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_dock.cpp +#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp +#: editor/project_settings_editor.cpp editor/scene_tree_dock.cpp msgid "Delete" msgstr "को हटा दें" @@ -1143,7 +1135,7 @@ msgid "Add Bus" msgstr "" #: editor/editor_audio_buses.cpp -msgid "Create a new Bus Layout." +msgid "Add a new Audio Bus to this layout." msgstr "" #: editor/editor_audio_buses.cpp editor/editor_properties.cpp @@ -1172,6 +1164,10 @@ msgstr "" msgid "Load the default Bus Layout." msgstr "" +#: editor/editor_audio_buses.cpp +msgid "Create a new Bus Layout." +msgstr "" + #: editor/editor_autoload_settings.cpp msgid "Invalid name." msgstr "" @@ -2352,7 +2348,7 @@ msgid "Save & Restart" msgstr "" #: editor/editor_node.cpp -msgid "Spins when the editor window repaints!" +msgid "Spins when the editor window redraws." msgstr "" #: editor/editor_node.cpp @@ -3408,23 +3404,6 @@ msgid "Create Polygon" msgstr "सदसà¥à¤¯à¤¤à¤¾ बनाà¤à¤‚" #: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Edit Polygon" -msgstr "सदसà¥à¤¯à¤¤à¤¾ बनाà¤à¤‚" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Insert Point" -msgstr "" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Edit Polygon (Remove Point)" -msgstr "" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Remove Polygon And Point" -msgstr "" - -#: editor/plugins/abstract_polygon_2d_editor.cpp #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #, fuzzy @@ -3443,6 +3422,23 @@ msgstr "" msgid "Erase points." msgstr "" +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Edit Polygon" +msgstr "सदसà¥à¤¯à¤¤à¤¾ बनाà¤à¤‚" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Insert Point" +msgstr "" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Edit Polygon (Remove Point)" +msgstr "" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Remove Polygon And Point" +msgstr "" + #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #: editor/plugins/animation_player_editor_plugin.cpp @@ -4229,6 +4225,16 @@ msgid "Move CanvasItem" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp +msgid "Presets for the anchors and margins values of a Control node." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp +msgid "" +"Children of containers have their anchors and margins values overridden by " +"their parent." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp msgid "Anchors only" msgstr "" @@ -5127,6 +5133,12 @@ msgid "Create UV Map" msgstr "" #: editor/plugins/polygon_2d_editor_plugin.cpp +msgid "" +"Polygon 2D has internal vertices, so it can no longer be edited in the " +"viewport." +msgstr "" + +#: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Create Polygon & UV" msgstr "" @@ -6224,7 +6236,7 @@ msgid "Post" msgstr "" #: editor/plugins/spatial_editor_plugin.cpp -msgid "Name-less gizmo" +msgid "Nameless gizmo" msgstr "" #: editor/plugins/sprite_editor_plugin.cpp @@ -6301,8 +6313,14 @@ msgid "(empty)" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animations" -msgstr "" +#, fuzzy +msgid "Animations:" +msgstr "कारà¥à¤¯à¥‹à¤‚:" + +#: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "New Animation" +msgstr "à¤à¤¨à¤¿à¤®à¥‡à¤¶à¤¨ लूप" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed (FPS):" @@ -6313,7 +6331,7 @@ msgid "Loop" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animation Frames" +msgid "Animation Frames:" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp @@ -7108,6 +7126,19 @@ msgstr "" #: editor/project_manager.cpp msgid "" +"The following project settings file does not specify the version of Godot " +"through which it was created.\n" +"\n" +"%s\n" +"\n" +"If you proceed with opening it, it will be converted to Godot's current " +"configuration file format.\n" +"Warning: You will not be able to open the project with previous versions of " +"the engine anymore." +msgstr "" + +#: editor/project_manager.cpp +msgid "" "The following project settings file was generated by an older engine " "version, and needs to be converted for this version:\n" "\n" @@ -8592,10 +8623,6 @@ msgid "Build Project" msgstr "" #: modules/mono/editor/mono_bottom_panel.cpp -msgid "Warnings" -msgstr "" - -#: modules/mono/editor/mono_bottom_panel.cpp msgid "View log" msgstr "" @@ -9226,6 +9253,13 @@ msgid "" "ParallaxLayer node only works when set as child of a ParallaxBackground node." msgstr "" +#: scene/2d/particles_2d.cpp +msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles2D node instead. You can use the \"Convert to " +"CPUParticles\" option for this purpose." +msgstr "" + #: scene/2d/particles_2d.cpp scene/3d/particles.cpp msgid "" "A material to process the particles is not assigned, so no behavior is " @@ -9381,6 +9415,13 @@ msgstr "" #: scene/3d/particles.cpp msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles node instead. You can use the \"Convert to CPUParticles" +"\" option for this purpose." +msgstr "" + +#: scene/3d/particles.cpp +msgid "" "Nothing is visible because meshes have not been assigned to draw passes." msgstr "" @@ -9411,21 +9452,6 @@ msgstr "" msgid "Path property must point to a valid Spatial node to work." msgstr "" -#: scene/3d/scenario_fx.cpp -msgid "WorldEnvironment needs an Environment resource." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " -"this environment's Background Mode to Canvas (for 2D scenes)." -msgstr "" - #: scene/3d/soft_body.cpp msgid "This body will be ignored until you set a mesh" msgstr "" @@ -9449,6 +9475,21 @@ msgid "" "it as a child of a VehicleBody." msgstr "" +#: scene/3d/world_environment.cpp +msgid "WorldEnvironment needs an Environment resource." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " +"this environment's Background Mode to Canvas (for 2D scenes)." +msgstr "" + #: scene/animation/animation_blend_tree.cpp msgid "On BlendTree node '%s', animation not found: '%s'" msgstr "" @@ -9492,11 +9533,19 @@ msgid "This node has been deprecated. Use AnimationTree instead." msgstr "" #: scene/gui/color_picker.cpp +msgid "Pick a color from the screen." +msgstr "" + +#: scene/gui/color_picker.cpp msgid "Raw Mode" msgstr "" #: scene/gui/color_picker.cpp -msgid "Add current color as a preset" +msgid "Switch between hexadecimal and code values." +msgstr "" + +#: scene/gui/color_picker.cpp +msgid "Add current color as a preset." msgstr "" #: scene/gui/dialogs.cpp @@ -9580,6 +9629,12 @@ msgstr "" msgid "Varyings can only be assigned in vertex function." msgstr "" +#~ msgid "Line:" +#~ msgstr "रेखा:" + +#~ msgid "Col:" +#~ msgstr "सà¥à¤¤à¤‚à¤:" + #, fuzzy #~ msgid "Remove Split" #~ msgstr "मिटाना" diff --git a/editor/translations/hr.po b/editor/translations/hr.po index 36017a4f78..ba06a478bb 100644 --- a/editor/translations/hr.po +++ b/editor/translations/hr.po @@ -531,20 +531,12 @@ msgstr "" msgid "Reset Zoom" msgstr "" -#: editor/code_editor.cpp -msgid "Warnings:" -msgstr "" - -#: editor/code_editor.cpp -msgid "Font Size:" -msgstr "" - -#: editor/code_editor.cpp -msgid "Line:" +#: editor/code_editor.cpp modules/mono/editor/mono_bottom_panel.cpp +msgid "Warnings" msgstr "" #: editor/code_editor.cpp -msgid "Col:" +msgid "Line and column numbers." msgstr "" #: editor/connections_dialog.cpp @@ -838,8 +830,8 @@ msgstr "" #: editor/dependency_editor.cpp editor/editor_audio_buses.cpp #: editor/editor_file_dialog.cpp editor/editor_node.cpp #: editor/filesystem_dock.cpp editor/plugins/item_list_editor_plugin.cpp -#: editor/project_export.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_dock.cpp +#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp +#: editor/project_settings_editor.cpp editor/scene_tree_dock.cpp msgid "Delete" msgstr "" @@ -1091,7 +1083,7 @@ msgid "Add Bus" msgstr "" #: editor/editor_audio_buses.cpp -msgid "Create a new Bus Layout." +msgid "Add a new Audio Bus to this layout." msgstr "" #: editor/editor_audio_buses.cpp editor/editor_properties.cpp @@ -1120,6 +1112,10 @@ msgstr "" msgid "Load the default Bus Layout." msgstr "" +#: editor/editor_audio_buses.cpp +msgid "Create a new Bus Layout." +msgstr "" + #: editor/editor_autoload_settings.cpp msgid "Invalid name." msgstr "" @@ -2290,7 +2286,7 @@ msgid "Save & Restart" msgstr "" #: editor/editor_node.cpp -msgid "Spins when the editor window repaints!" +msgid "Spins when the editor window redraws." msgstr "" #: editor/editor_node.cpp @@ -3328,37 +3324,37 @@ msgid "Create Polygon" msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Edit Polygon" +#: editor/plugins/animation_blend_space_1d_editor.cpp +#: editor/plugins/animation_blend_space_2d_editor.cpp +msgid "Create points." msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Insert Point" +msgid "" +"Edit points.\n" +"LMB: Move Point\n" +"RMB: Erase Point" msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Edit Polygon (Remove Point)" +#: editor/plugins/animation_blend_space_1d_editor.cpp +msgid "Erase points." msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Remove Polygon And Point" +msgid "Edit Polygon" msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -#: editor/plugins/animation_blend_space_1d_editor.cpp -#: editor/plugins/animation_blend_space_2d_editor.cpp -msgid "Create points." +msgid "Insert Point" msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "" -"Edit points.\n" -"LMB: Move Point\n" -"RMB: Erase Point" +msgid "Edit Polygon (Remove Point)" msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -#: editor/plugins/animation_blend_space_1d_editor.cpp -msgid "Erase points." +msgid "Remove Polygon And Point" msgstr "" #: editor/plugins/animation_blend_space_1d_editor.cpp @@ -4141,6 +4137,16 @@ msgid "Move CanvasItem" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp +msgid "Presets for the anchors and margins values of a Control node." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp +msgid "" +"Children of containers have their anchors and margins values overridden by " +"their parent." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp msgid "Anchors only" msgstr "" @@ -5036,6 +5042,12 @@ msgid "Create UV Map" msgstr "" #: editor/plugins/polygon_2d_editor_plugin.cpp +msgid "" +"Polygon 2D has internal vertices, so it can no longer be edited in the " +"viewport." +msgstr "" + +#: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Create Polygon & UV" msgstr "" @@ -6117,7 +6129,7 @@ msgid "Post" msgstr "" #: editor/plugins/spatial_editor_plugin.cpp -msgid "Name-less gizmo" +msgid "Nameless gizmo" msgstr "" #: editor/plugins/sprite_editor_plugin.cpp @@ -6193,7 +6205,11 @@ msgid "(empty)" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animations" +msgid "Animations:" +msgstr "" + +#: editor/plugins/sprite_frames_editor_plugin.cpp +msgid "New Animation" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp @@ -6205,7 +6221,7 @@ msgid "Loop" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animation Frames" +msgid "Animation Frames:" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp @@ -6981,6 +6997,19 @@ msgstr "" #: editor/project_manager.cpp msgid "" +"The following project settings file does not specify the version of Godot " +"through which it was created.\n" +"\n" +"%s\n" +"\n" +"If you proceed with opening it, it will be converted to Godot's current " +"configuration file format.\n" +"Warning: You will not be able to open the project with previous versions of " +"the engine anymore." +msgstr "" + +#: editor/project_manager.cpp +msgid "" "The following project settings file was generated by an older engine " "version, and needs to be converted for this version:\n" "\n" @@ -8457,10 +8486,6 @@ msgid "Build Project" msgstr "" #: modules/mono/editor/mono_bottom_panel.cpp -msgid "Warnings" -msgstr "" - -#: modules/mono/editor/mono_bottom_panel.cpp msgid "View log" msgstr "" @@ -9086,6 +9111,13 @@ msgid "" "ParallaxLayer node only works when set as child of a ParallaxBackground node." msgstr "" +#: scene/2d/particles_2d.cpp +msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles2D node instead. You can use the \"Convert to " +"CPUParticles\" option for this purpose." +msgstr "" + #: scene/2d/particles_2d.cpp scene/3d/particles.cpp msgid "" "A material to process the particles is not assigned, so no behavior is " @@ -9241,6 +9273,13 @@ msgstr "" #: scene/3d/particles.cpp msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles node instead. You can use the \"Convert to CPUParticles" +"\" option for this purpose." +msgstr "" + +#: scene/3d/particles.cpp +msgid "" "Nothing is visible because meshes have not been assigned to draw passes." msgstr "" @@ -9271,21 +9310,6 @@ msgstr "" msgid "Path property must point to a valid Spatial node to work." msgstr "" -#: scene/3d/scenario_fx.cpp -msgid "WorldEnvironment needs an Environment resource." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " -"this environment's Background Mode to Canvas (for 2D scenes)." -msgstr "" - #: scene/3d/soft_body.cpp msgid "This body will be ignored until you set a mesh" msgstr "" @@ -9309,6 +9333,21 @@ msgid "" "it as a child of a VehicleBody." msgstr "" +#: scene/3d/world_environment.cpp +msgid "WorldEnvironment needs an Environment resource." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " +"this environment's Background Mode to Canvas (for 2D scenes)." +msgstr "" + #: scene/animation/animation_blend_tree.cpp msgid "On BlendTree node '%s', animation not found: '%s'" msgstr "" @@ -9350,11 +9389,19 @@ msgid "This node has been deprecated. Use AnimationTree instead." msgstr "" #: scene/gui/color_picker.cpp +msgid "Pick a color from the screen." +msgstr "" + +#: scene/gui/color_picker.cpp msgid "Raw Mode" msgstr "" #: scene/gui/color_picker.cpp -msgid "Add current color as a preset" +msgid "Switch between hexadecimal and code values." +msgstr "" + +#: scene/gui/color_picker.cpp +msgid "Add current color as a preset." msgstr "" #: scene/gui/dialogs.cpp diff --git a/editor/translations/hu.po b/editor/translations/hu.po index 15932c95bf..def006f056 100644 --- a/editor/translations/hu.po +++ b/editor/translations/hu.po @@ -565,22 +565,13 @@ msgstr "KicsinyÃtés" msgid "Reset Zoom" msgstr "NagyÃtás VisszaállÃtása" -#: editor/code_editor.cpp -msgid "Warnings:" +#: editor/code_editor.cpp modules/mono/editor/mono_bottom_panel.cpp +msgid "Warnings" msgstr "" #: editor/code_editor.cpp -#, fuzzy -msgid "Font Size:" -msgstr "Körvonal Mérete:" - -#: editor/code_editor.cpp -msgid "Line:" -msgstr "Sor:" - -#: editor/code_editor.cpp -msgid "Col:" -msgstr "Oszlop:" +msgid "Line and column numbers." +msgstr "" #: editor/connections_dialog.cpp msgid "Method in target Node must be specified!" @@ -888,8 +879,8 @@ msgstr "Törli a kiválasztott fájlokat?" #: editor/dependency_editor.cpp editor/editor_audio_buses.cpp #: editor/editor_file_dialog.cpp editor/editor_node.cpp #: editor/filesystem_dock.cpp editor/plugins/item_list_editor_plugin.cpp -#: editor/project_export.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_dock.cpp +#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp +#: editor/project_settings_editor.cpp editor/scene_tree_dock.cpp msgid "Delete" msgstr "Törlés" @@ -1146,8 +1137,9 @@ msgid "Add Bus" msgstr "Busz Hozzáadása" #: editor/editor_audio_buses.cpp -msgid "Create a new Bus Layout." -msgstr "Új Buszelrendezés létrehozása." +#, fuzzy +msgid "Add a new Audio Bus to this layout." +msgstr "Hangbusz Elrendezés Mentése Másként..." #: editor/editor_audio_buses.cpp editor/editor_properties.cpp #: editor/plugins/animation_player_editor_plugin.cpp editor/property_editor.cpp @@ -1175,6 +1167,10 @@ msgstr "Alapértelmezett Betöltése" msgid "Load the default Bus Layout." msgstr "Betölti az alapértelmezett Busz Elrendezést." +#: editor/editor_audio_buses.cpp +msgid "Create a new Bus Layout." +msgstr "Új Buszelrendezés létrehozása." + #: editor/editor_autoload_settings.cpp msgid "Invalid name." msgstr "Érvénytelen név." @@ -2455,7 +2451,8 @@ msgid "Save & Restart" msgstr "Mentés és Kilépés" #: editor/editor_node.cpp -msgid "Spins when the editor window repaints!" +#, fuzzy +msgid "Spins when the editor window redraws." msgstr "Fordul egyet, amikor a szerkesztÅ‘ablak újrarajzolódik!" #: editor/editor_node.cpp @@ -3548,25 +3545,6 @@ msgid "Create Polygon" msgstr "Sokszög Létrehozása" #: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Edit Polygon" -msgstr "Sokszög Szerkesztése" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Insert Point" -msgstr "Pont Beszúrása" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Edit Polygon (Remove Point)" -msgstr "Sokszög Szerkesztése (Pont EltávolÃtása)" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Remove Polygon And Point" -msgstr "Sokszög és Pont EltávolÃtása" - -#: editor/plugins/abstract_polygon_2d_editor.cpp #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #, fuzzy @@ -3591,6 +3569,25 @@ msgstr "" msgid "Erase points." msgstr "Jobb Egérgomb: Pont Törlése." +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Edit Polygon" +msgstr "Sokszög Szerkesztése" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Insert Point" +msgstr "Pont Beszúrása" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Edit Polygon (Remove Point)" +msgstr "Sokszög Szerkesztése (Pont EltávolÃtása)" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Remove Polygon And Point" +msgstr "Sokszög és Pont EltávolÃtása" + #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #: editor/plugins/animation_player_editor_plugin.cpp @@ -4411,6 +4408,16 @@ msgid "Move CanvasItem" msgstr "CanvasItem Szerkesztése" #: editor/plugins/canvas_item_editor_plugin.cpp +msgid "Presets for the anchors and margins values of a Control node." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp +msgid "" +"Children of containers have their anchors and margins values overridden by " +"their parent." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp msgid "Anchors only" msgstr "Csak Horgonyok" @@ -5330,6 +5337,12 @@ msgid "Create UV Map" msgstr "UV Térkép Létrehozása" #: editor/plugins/polygon_2d_editor_plugin.cpp +msgid "" +"Polygon 2D has internal vertices, so it can no longer be edited in the " +"viewport." +msgstr "" + +#: editor/plugins/polygon_2d_editor_plugin.cpp #, fuzzy msgid "Create Polygon & UV" msgstr "Sokszög Létrehozása" @@ -6463,7 +6476,7 @@ msgid "Post" msgstr "" #: editor/plugins/spatial_editor_plugin.cpp -msgid "Name-less gizmo" +msgid "Nameless gizmo" msgstr "" #: editor/plugins/sprite_editor_plugin.cpp @@ -6544,8 +6557,14 @@ msgid "(empty)" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animations" -msgstr "" +#, fuzzy +msgid "Animations:" +msgstr "Animáció" + +#: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "New Animation" +msgstr "Animáció" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed (FPS):" @@ -6556,8 +6575,9 @@ msgid "Loop" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animation Frames" -msgstr "" +#, fuzzy +msgid "Animation Frames:" +msgstr "Animáció Neve:" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Insert Empty (Before)" @@ -7371,6 +7391,19 @@ msgstr "" #: editor/project_manager.cpp msgid "" +"The following project settings file does not specify the version of Godot " +"through which it was created.\n" +"\n" +"%s\n" +"\n" +"If you proceed with opening it, it will be converted to Godot's current " +"configuration file format.\n" +"Warning: You will not be able to open the project with previous versions of " +"the engine anymore." +msgstr "" + +#: editor/project_manager.cpp +msgid "" "The following project settings file was generated by an older engine " "version, and needs to be converted for this version:\n" "\n" @@ -8876,10 +8909,6 @@ msgid "Build Project" msgstr "" #: modules/mono/editor/mono_bottom_panel.cpp -msgid "Warnings" -msgstr "" - -#: modules/mono/editor/mono_bottom_panel.cpp #, fuzzy msgid "View log" msgstr "Fájlok Megtekintése" @@ -9522,6 +9551,13 @@ msgid "" "ParallaxLayer node only works when set as child of a ParallaxBackground node." msgstr "" +#: scene/2d/particles_2d.cpp +msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles2D node instead. You can use the \"Convert to " +"CPUParticles\" option for this purpose." +msgstr "" + #: scene/2d/particles_2d.cpp scene/3d/particles.cpp msgid "" "A material to process the particles is not assigned, so no behavior is " @@ -9677,6 +9713,13 @@ msgstr "" #: scene/3d/particles.cpp msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles node instead. You can use the \"Convert to CPUParticles" +"\" option for this purpose." +msgstr "" + +#: scene/3d/particles.cpp +msgid "" "Nothing is visible because meshes have not been assigned to draw passes." msgstr "" @@ -9707,21 +9750,6 @@ msgstr "" msgid "Path property must point to a valid Spatial node to work." msgstr "" -#: scene/3d/scenario_fx.cpp -msgid "WorldEnvironment needs an Environment resource." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " -"this environment's Background Mode to Canvas (for 2D scenes)." -msgstr "" - #: scene/3d/soft_body.cpp msgid "This body will be ignored until you set a mesh" msgstr "" @@ -9745,6 +9773,21 @@ msgid "" "it as a child of a VehicleBody." msgstr "" +#: scene/3d/world_environment.cpp +msgid "WorldEnvironment needs an Environment resource." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " +"this environment's Background Mode to Canvas (for 2D scenes)." +msgstr "" + #: scene/animation/animation_blend_tree.cpp msgid "On BlendTree node '%s', animation not found: '%s'" msgstr "" @@ -9793,11 +9836,19 @@ msgid "This node has been deprecated. Use AnimationTree instead." msgstr "" #: scene/gui/color_picker.cpp +msgid "Pick a color from the screen." +msgstr "" + +#: scene/gui/color_picker.cpp msgid "Raw Mode" msgstr "" #: scene/gui/color_picker.cpp -msgid "Add current color as a preset" +msgid "Switch between hexadecimal and code values." +msgstr "" + +#: scene/gui/color_picker.cpp +msgid "Add current color as a preset." msgstr "" #: scene/gui/dialogs.cpp @@ -9887,6 +9938,16 @@ msgid "Varyings can only be assigned in vertex function." msgstr "" #, fuzzy +#~ msgid "Font Size:" +#~ msgstr "Körvonal Mérete:" + +#~ msgid "Line:" +#~ msgstr "Sor:" + +#~ msgid "Col:" +#~ msgstr "Oszlop:" + +#, fuzzy #~ msgid "Split already exists." #~ msgstr "Már létezik '%s' AutoLoad!" diff --git a/editor/translations/id.po b/editor/translations/id.po index 6f399a2ae3..b850071957 100644 --- a/editor/translations/id.po +++ b/editor/translations/id.po @@ -561,22 +561,13 @@ msgstr "Perkecil Pandangan" msgid "Reset Zoom" msgstr "Kebalikan Semula Pandangan" -#: editor/code_editor.cpp -msgid "Warnings:" -msgstr "Peringatan:" - -#: editor/code_editor.cpp -#, fuzzy -msgid "Font Size:" -msgstr "Tampilan Depan." - -#: editor/code_editor.cpp -msgid "Line:" -msgstr "Baris:" +#: editor/code_editor.cpp modules/mono/editor/mono_bottom_panel.cpp +msgid "Warnings" +msgstr "" #: editor/code_editor.cpp -msgid "Col:" -msgstr "Kolom:" +msgid "Line and column numbers." +msgstr "" #: editor/connections_dialog.cpp msgid "Method in target Node must be specified!" @@ -881,8 +872,8 @@ msgstr "Hapus file yang dipilih?" #: editor/dependency_editor.cpp editor/editor_audio_buses.cpp #: editor/editor_file_dialog.cpp editor/editor_node.cpp #: editor/filesystem_dock.cpp editor/plugins/item_list_editor_plugin.cpp -#: editor/project_export.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_dock.cpp +#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp +#: editor/project_settings_editor.cpp editor/scene_tree_dock.cpp msgid "Delete" msgstr "Hapus" @@ -1140,8 +1131,9 @@ msgid "Add Bus" msgstr "Tambahkan Bus" #: editor/editor_audio_buses.cpp -msgid "Create a new Bus Layout." -msgstr "Buat Layout Bus Baru." +#, fuzzy +msgid "Add a new Audio Bus to this layout." +msgstr "Simpan Layout Suara Bus Ke..." #: editor/editor_audio_buses.cpp editor/editor_properties.cpp #: editor/plugins/animation_player_editor_plugin.cpp editor/property_editor.cpp @@ -1169,6 +1161,10 @@ msgstr "Muat Default" msgid "Load the default Bus Layout." msgstr "Muat default Layout Bus." +#: editor/editor_audio_buses.cpp +msgid "Create a new Bus Layout." +msgstr "Buat Layout Bus Baru." + #: editor/editor_autoload_settings.cpp msgid "Invalid name." msgstr "Nama tidak sah." @@ -2437,7 +2433,8 @@ msgid "Save & Restart" msgstr "Simpan & Keluar" #: editor/editor_node.cpp -msgid "Spins when the editor window repaints!" +#, fuzzy +msgid "Spins when the editor window redraws." msgstr "Putar ketika jendela editor cat ulang!" #: editor/editor_node.cpp @@ -3546,25 +3543,6 @@ msgid "Create Polygon" msgstr "Buat Bidang" #: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Edit Polygon" -msgstr "Sunting Bidang" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Insert Point" -msgstr "Tambah Titik" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Edit Polygon (Remove Point)" -msgstr "Sunting Bidang (Hapus Titik)" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Remove Polygon And Point" -msgstr "Hapus Bidang dan Titik" - -#: editor/plugins/abstract_polygon_2d_editor.cpp #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #, fuzzy @@ -3589,6 +3567,25 @@ msgstr "" msgid "Erase points." msgstr "Beri Skala Seleksi" +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Edit Polygon" +msgstr "Sunting Bidang" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Insert Point" +msgstr "Tambah Titik" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Edit Polygon (Remove Point)" +msgstr "Sunting Bidang (Hapus Titik)" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Remove Polygon And Point" +msgstr "Hapus Bidang dan Titik" + #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #: editor/plugins/animation_player_editor_plugin.cpp @@ -4429,6 +4426,16 @@ msgid "Move CanvasItem" msgstr "Sunting CanvasItem" #: editor/plugins/canvas_item_editor_plugin.cpp +msgid "Presets for the anchors and margins values of a Control node." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp +msgid "" +"Children of containers have their anchors and margins values overridden by " +"their parent." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp msgid "Anchors only" msgstr "" @@ -5351,6 +5358,12 @@ msgid "Create UV Map" msgstr "" #: editor/plugins/polygon_2d_editor_plugin.cpp +msgid "" +"Polygon 2D has internal vertices, so it can no longer be edited in the " +"viewport." +msgstr "" + +#: editor/plugins/polygon_2d_editor_plugin.cpp #, fuzzy msgid "Create Polygon & UV" msgstr "Buat Bidang" @@ -6499,7 +6512,7 @@ msgid "Post" msgstr "" #: editor/plugins/spatial_editor_plugin.cpp -msgid "Name-less gizmo" +msgid "Nameless gizmo" msgstr "" #: editor/plugins/sprite_editor_plugin.cpp @@ -6579,8 +6592,14 @@ msgid "(empty)" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animations" -msgstr "" +#, fuzzy +msgid "Animations:" +msgstr "Animasi" + +#: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "New Animation" +msgstr "Animasi" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed (FPS):" @@ -6591,8 +6610,9 @@ msgid "Loop" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animation Frames" -msgstr "" +#, fuzzy +msgid "Animation Frames:" +msgstr "Nama Animasi:" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Insert Empty (Before)" @@ -7431,6 +7451,19 @@ msgstr "Apakah Anda yakin membuka lebih dari satu projek?" #: editor/project_manager.cpp msgid "" +"The following project settings file does not specify the version of Godot " +"through which it was created.\n" +"\n" +"%s\n" +"\n" +"If you proceed with opening it, it will be converted to Godot's current " +"configuration file format.\n" +"Warning: You will not be able to open the project with previous versions of " +"the engine anymore." +msgstr "" + +#: editor/project_manager.cpp +msgid "" "The following project settings file was generated by an older engine " "version, and needs to be converted for this version:\n" "\n" @@ -9000,10 +9033,6 @@ msgid "Build Project" msgstr "Proyek" #: modules/mono/editor/mono_bottom_panel.cpp -msgid "Warnings" -msgstr "" - -#: modules/mono/editor/mono_bottom_panel.cpp #, fuzzy msgid "View log" msgstr "File:" @@ -9703,6 +9732,13 @@ msgstr "" "Node ParallaxLayer hanya bekerja ketika diatur sebagai child dari sebuah " "node ParallaxBackground." +#: scene/2d/particles_2d.cpp +msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles2D node instead. You can use the \"Convert to " +"CPUParticles\" option for this purpose." +msgstr "" + #: scene/2d/particles_2d.cpp scene/3d/particles.cpp msgid "" "A material to process the particles is not assigned, so no behavior is " @@ -9877,6 +9913,13 @@ msgstr "" #: scene/3d/particles.cpp msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles node instead. You can use the \"Convert to CPUParticles" +"\" option for this purpose." +msgstr "" + +#: scene/3d/particles.cpp +msgid "" "Nothing is visible because meshes have not been assigned to draw passes." msgstr "" @@ -9913,23 +9956,6 @@ msgstr "" "Properti path harus menunjuk ke sebuah node Particles2D yang sah agar " "bekerja." -#: scene/3d/scenario_fx.cpp -msgid "WorldEnvironment needs an Environment resource." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." -msgstr "" -"Hanya satu WorldEnvironment yang diizinkan per scene (atau atur scene-scene " -"yang diacu)." - -#: scene/3d/scenario_fx.cpp -msgid "" -"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " -"this environment's Background Mode to Canvas (for 2D scenes)." -msgstr "" - #: scene/3d/soft_body.cpp msgid "This body will be ignored until you set a mesh" msgstr "" @@ -9955,6 +9981,23 @@ msgid "" "it as a child of a VehicleBody." msgstr "" +#: scene/3d/world_environment.cpp +msgid "WorldEnvironment needs an Environment resource." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." +msgstr "" +"Hanya satu WorldEnvironment yang diizinkan per scene (atau atur scene-scene " +"yang diacu)." + +#: scene/3d/world_environment.cpp +msgid "" +"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " +"this environment's Background Mode to Canvas (for 2D scenes)." +msgstr "" + #: scene/animation/animation_blend_tree.cpp msgid "On BlendTree node '%s', animation not found: '%s'" msgstr "" @@ -10000,11 +10043,20 @@ msgid "This node has been deprecated. Use AnimationTree instead." msgstr "" #: scene/gui/color_picker.cpp +msgid "Pick a color from the screen." +msgstr "" + +#: scene/gui/color_picker.cpp msgid "Raw Mode" msgstr "" #: scene/gui/color_picker.cpp -msgid "Add current color as a preset" +msgid "Switch between hexadecimal and code values." +msgstr "" + +#: scene/gui/color_picker.cpp +#, fuzzy +msgid "Add current color as a preset." msgstr "Tambahkan warna yang sekarang sebagai preset" #: scene/gui/dialogs.cpp @@ -10100,6 +10152,19 @@ msgstr "" msgid "Varyings can only be assigned in vertex function." msgstr "" +#~ msgid "Warnings:" +#~ msgstr "Peringatan:" + +#, fuzzy +#~ msgid "Font Size:" +#~ msgstr "Tampilan Depan." + +#~ msgid "Line:" +#~ msgstr "Baris:" + +#~ msgid "Col:" +#~ msgstr "Kolom:" + #, fuzzy #~ msgid "OrientedPathFollow only works when set as a child of a Path node." #~ msgstr "" diff --git a/editor/translations/is.po b/editor/translations/is.po index 0f42409c0d..6b2588ca26 100644 --- a/editor/translations/is.po +++ b/editor/translations/is.po @@ -552,20 +552,12 @@ msgstr "" msgid "Reset Zoom" msgstr "" -#: editor/code_editor.cpp -msgid "Warnings:" -msgstr "" - -#: editor/code_editor.cpp -msgid "Font Size:" -msgstr "" - -#: editor/code_editor.cpp -msgid "Line:" +#: editor/code_editor.cpp modules/mono/editor/mono_bottom_panel.cpp +msgid "Warnings" msgstr "" #: editor/code_editor.cpp -msgid "Col:" +msgid "Line and column numbers." msgstr "" #: editor/connections_dialog.cpp @@ -859,8 +851,8 @@ msgstr "" #: editor/dependency_editor.cpp editor/editor_audio_buses.cpp #: editor/editor_file_dialog.cpp editor/editor_node.cpp #: editor/filesystem_dock.cpp editor/plugins/item_list_editor_plugin.cpp -#: editor/project_export.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_dock.cpp +#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp +#: editor/project_settings_editor.cpp editor/scene_tree_dock.cpp msgid "Delete" msgstr "" @@ -1112,7 +1104,7 @@ msgid "Add Bus" msgstr "" #: editor/editor_audio_buses.cpp -msgid "Create a new Bus Layout." +msgid "Add a new Audio Bus to this layout." msgstr "" #: editor/editor_audio_buses.cpp editor/editor_properties.cpp @@ -1141,6 +1133,10 @@ msgstr "" msgid "Load the default Bus Layout." msgstr "" +#: editor/editor_audio_buses.cpp +msgid "Create a new Bus Layout." +msgstr "" + #: editor/editor_autoload_settings.cpp msgid "Invalid name." msgstr "" @@ -2313,7 +2309,7 @@ msgid "Save & Restart" msgstr "" #: editor/editor_node.cpp -msgid "Spins when the editor window repaints!" +msgid "Spins when the editor window redraws." msgstr "" #: editor/editor_node.cpp @@ -3352,38 +3348,38 @@ msgid "Create Polygon" msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Edit Polygon" -msgstr "Breyta Viðbót" +#: editor/plugins/animation_blend_space_1d_editor.cpp +#: editor/plugins/animation_blend_space_2d_editor.cpp +msgid "Create points." +msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Insert Point" +msgid "" +"Edit points.\n" +"LMB: Move Point\n" +"RMB: Erase Point" msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Edit Polygon (Remove Point)" +#: editor/plugins/animation_blend_space_1d_editor.cpp +msgid "Erase points." msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Remove Polygon And Point" -msgstr "" +#, fuzzy +msgid "Edit Polygon" +msgstr "Breyta Viðbót" #: editor/plugins/abstract_polygon_2d_editor.cpp -#: editor/plugins/animation_blend_space_1d_editor.cpp -#: editor/plugins/animation_blend_space_2d_editor.cpp -msgid "Create points." +msgid "Insert Point" msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "" -"Edit points.\n" -"LMB: Move Point\n" -"RMB: Erase Point" +msgid "Edit Polygon (Remove Point)" msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -#: editor/plugins/animation_blend_space_1d_editor.cpp -msgid "Erase points." +msgid "Remove Polygon And Point" msgstr "" #: editor/plugins/animation_blend_space_1d_editor.cpp @@ -4169,6 +4165,16 @@ msgid "Move CanvasItem" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp +msgid "Presets for the anchors and margins values of a Control node." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp +msgid "" +"Children of containers have their anchors and margins values overridden by " +"their parent." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp msgid "Anchors only" msgstr "" @@ -5065,6 +5071,12 @@ msgid "Create UV Map" msgstr "" #: editor/plugins/polygon_2d_editor_plugin.cpp +msgid "" +"Polygon 2D has internal vertices, so it can no longer be edited in the " +"viewport." +msgstr "" + +#: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Create Polygon & UV" msgstr "" @@ -6148,7 +6160,7 @@ msgid "Post" msgstr "" #: editor/plugins/spatial_editor_plugin.cpp -msgid "Name-less gizmo" +msgid "Nameless gizmo" msgstr "" #: editor/plugins/sprite_editor_plugin.cpp @@ -6224,7 +6236,12 @@ msgid "(empty)" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animations" +#, fuzzy +msgid "Animations:" +msgstr "Stillið breyting á:" + +#: editor/plugins/sprite_frames_editor_plugin.cpp +msgid "New Animation" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp @@ -6236,7 +6253,7 @@ msgid "Loop" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animation Frames" +msgid "Animation Frames:" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp @@ -7024,6 +7041,19 @@ msgstr "" #: editor/project_manager.cpp msgid "" +"The following project settings file does not specify the version of Godot " +"through which it was created.\n" +"\n" +"%s\n" +"\n" +"If you proceed with opening it, it will be converted to Godot's current " +"configuration file format.\n" +"Warning: You will not be able to open the project with previous versions of " +"the engine anymore." +msgstr "" + +#: editor/project_manager.cpp +msgid "" "The following project settings file was generated by an older engine " "version, and needs to be converted for this version:\n" "\n" @@ -8506,10 +8536,6 @@ msgid "Build Project" msgstr "" #: modules/mono/editor/mono_bottom_panel.cpp -msgid "Warnings" -msgstr "" - -#: modules/mono/editor/mono_bottom_panel.cpp msgid "View log" msgstr "" @@ -9135,6 +9161,13 @@ msgid "" "ParallaxLayer node only works when set as child of a ParallaxBackground node." msgstr "" +#: scene/2d/particles_2d.cpp +msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles2D node instead. You can use the \"Convert to " +"CPUParticles\" option for this purpose." +msgstr "" + #: scene/2d/particles_2d.cpp scene/3d/particles.cpp msgid "" "A material to process the particles is not assigned, so no behavior is " @@ -9290,6 +9323,13 @@ msgstr "" #: scene/3d/particles.cpp msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles node instead. You can use the \"Convert to CPUParticles" +"\" option for this purpose." +msgstr "" + +#: scene/3d/particles.cpp +msgid "" "Nothing is visible because meshes have not been assigned to draw passes." msgstr "" @@ -9320,21 +9360,6 @@ msgstr "" msgid "Path property must point to a valid Spatial node to work." msgstr "" -#: scene/3d/scenario_fx.cpp -msgid "WorldEnvironment needs an Environment resource." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " -"this environment's Background Mode to Canvas (for 2D scenes)." -msgstr "" - #: scene/3d/soft_body.cpp msgid "This body will be ignored until you set a mesh" msgstr "" @@ -9358,6 +9383,21 @@ msgid "" "it as a child of a VehicleBody." msgstr "" +#: scene/3d/world_environment.cpp +msgid "WorldEnvironment needs an Environment resource." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " +"this environment's Background Mode to Canvas (for 2D scenes)." +msgstr "" + #: scene/animation/animation_blend_tree.cpp msgid "On BlendTree node '%s', animation not found: '%s'" msgstr "" @@ -9399,11 +9439,19 @@ msgid "This node has been deprecated. Use AnimationTree instead." msgstr "" #: scene/gui/color_picker.cpp +msgid "Pick a color from the screen." +msgstr "" + +#: scene/gui/color_picker.cpp msgid "Raw Mode" msgstr "" #: scene/gui/color_picker.cpp -msgid "Add current color as a preset" +msgid "Switch between hexadecimal and code values." +msgstr "" + +#: scene/gui/color_picker.cpp +msgid "Add current color as a preset." msgstr "" #: scene/gui/dialogs.cpp diff --git a/editor/translations/it.po b/editor/translations/it.po index 693e07ba94..97f764a309 100644 --- a/editor/translations/it.po +++ b/editor/translations/it.po @@ -12,7 +12,7 @@ # Matteo <matteo.guglielmetti@hotmail.it>, 2018. # Myself <whatamidoing.wt@gmail.com>, 2017-2018. # RealAquilus <JamesHeller@live.it>, 2017. -# Samuele Zolfanelli <samdazel@gmail.com>, 2018. +# Samuele Zolfanelli <samdazel@gmail.com>, 2018, 2019. # Sean Bone <seanbone@zumguy.com>, 2017. # Red Pill <redpill902@gmail.com>, 2018. # iRadEntertainment <devitadario@gmail.com>, 2018. @@ -27,12 +27,13 @@ # Hairic95 <hairic95@gmail.com>, 2019. # Christian Biffi <creixx@virgilio.it>, 2019. # Giuseppe Guerra <me@nyodev.xyz>, 2019. +# RHC <rhc.throwaway@gmail.com>, 2019. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2019-01-26 13:31+0000\n" -"Last-Translator: Giuseppe Guerra <me@nyodev.xyz>\n" +"PO-Revision-Date: 2019-02-18 08:54+0000\n" +"Last-Translator: RHC <rhc.throwaway@gmail.com>\n" "Language-Team: Italian <https://hosted.weblate.org/projects/godot-engine/" "godot/it/>\n" "Language: it\n" @@ -66,7 +67,7 @@ msgstr "self non può essere usato perché l'istanza è nulla (non passata)" #: core/math/expression.cpp #, fuzzy msgid "Invalid operands to operator %s, %s and %s." -msgstr "Nome proprietà indice invalido '%s' nel nodo %s." +msgstr "Utilizzo errato dell'operatore %s, operandi %s e %s non validi." #: core/math/expression.cpp #, fuzzy @@ -157,8 +158,9 @@ msgid "Bezier Curve Track" msgstr "Traccia Curva di Bezier" #: editor/animation_track_editor.cpp +#, fuzzy msgid "Audio Playback Track" -msgstr "" +msgstr "Traccia di Riproduzione Audio" #: editor/animation_track_editor.cpp #, fuzzy @@ -197,8 +199,9 @@ msgid "Toggle this track on/off." msgstr "Attiva/Disattiva la traccia." #: editor/animation_track_editor.cpp +#, fuzzy msgid "Update Mode (How this property is set)" -msgstr "" +msgstr "Modalità di Aggiornamento (come viene impostata questa proprietà )" #: editor/animation_track_editor.cpp #, fuzzy @@ -323,6 +326,10 @@ msgid "" "-AudioStreamPlayer2D\n" "-AudioStreamPlayer3D" msgstr "" +"Le tracce audio possono puntare solo a nodi di tipo:\n" +"-AudioStreamPlayer\n" +"-AudioStreamPlayer2D\n" +"-AudioStreamPlayer3D" #: editor/animation_track_editor.cpp msgid "Animation tracks can only point to AnimationPlayer nodes." @@ -337,12 +344,14 @@ msgid "Not possible to add a new track without a root" msgstr "" #: editor/animation_track_editor.cpp +#, fuzzy msgid "Track path is invalid, so can't add a key." -msgstr "" +msgstr "Il tracciato non è valido, non è possibile aggiungere una chiave." #: editor/animation_track_editor.cpp +#, fuzzy msgid "Track is not of type Spatial, can't insert key" -msgstr "" +msgstr "La traccia non è di tipo Spatial, impossibile aggiungere la chiave." #: editor/animation_track_editor.cpp msgid "Track path is invalid, so can't add a method key." @@ -576,22 +585,14 @@ msgstr "Zoom Out" msgid "Reset Zoom" msgstr "Resetta Zoom" -#: editor/code_editor.cpp +#: editor/code_editor.cpp modules/mono/editor/mono_bottom_panel.cpp #, fuzzy -msgid "Warnings:" +msgid "Warnings" msgstr "Avvertimento" #: editor/code_editor.cpp -msgid "Font Size:" -msgstr "Dimensione Font:" - -#: editor/code_editor.cpp -msgid "Line:" -msgstr "Riga:" - -#: editor/code_editor.cpp -msgid "Col:" -msgstr "Col:" +msgid "Line and column numbers." +msgstr "" #: editor/connections_dialog.cpp msgid "Method in target Node must be specified!" @@ -897,8 +898,8 @@ msgstr "Eliminare i file selezionati?" #: editor/dependency_editor.cpp editor/editor_audio_buses.cpp #: editor/editor_file_dialog.cpp editor/editor_node.cpp #: editor/filesystem_dock.cpp editor/plugins/item_list_editor_plugin.cpp -#: editor/project_export.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_dock.cpp +#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp +#: editor/project_settings_editor.cpp editor/scene_tree_dock.cpp msgid "Delete" msgstr "Elimina" @@ -1155,8 +1156,9 @@ msgid "Add Bus" msgstr "Aggiungi Bus" #: editor/editor_audio_buses.cpp -msgid "Create a new Bus Layout." -msgstr "Crea nuovo layout di tipo bus." +#, fuzzy +msgid "Add a new Audio Bus to this layout." +msgstr "Salva Layout Bus Audio Come..." #: editor/editor_audio_buses.cpp editor/editor_properties.cpp #: editor/plugins/animation_player_editor_plugin.cpp editor/property_editor.cpp @@ -1184,6 +1186,10 @@ msgstr "Carica predefiniti" msgid "Load the default Bus Layout." msgstr "Carica il layout di tipo bus predefinito." +#: editor/editor_audio_buses.cpp +msgid "Create a new Bus Layout." +msgstr "Crea nuovo layout di tipo bus." + #: editor/editor_autoload_settings.cpp msgid "Invalid name." msgstr "Nome Invalido." @@ -2445,7 +2451,8 @@ msgid "Save & Restart" msgstr "Salva e Re-Importa" #: editor/editor_node.cpp -msgid "Spins when the editor window repaints!" +#, fuzzy +msgid "Spins when the editor window redraws." msgstr "Gira quando la finestra dell'editor viene ridisegnata!" #: editor/editor_node.cpp @@ -3549,25 +3556,6 @@ msgid "Create Polygon" msgstr "Crea Poly" #: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Edit Polygon" -msgstr "Modifica Poly" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Insert Point" -msgstr "Inserisci Punto" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Edit Polygon (Remove Point)" -msgstr "Modifica Poly (Rimuovi Punto)" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Remove Polygon And Point" -msgstr "Rimuovi Poligono e Punto" - -#: editor/plugins/abstract_polygon_2d_editor.cpp #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #, fuzzy @@ -3592,6 +3580,25 @@ msgstr "" msgid "Erase points." msgstr "RMB: Elimina Punto." +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Edit Polygon" +msgstr "Modifica Poly" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Insert Point" +msgstr "Inserisci Punto" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Edit Polygon (Remove Point)" +msgstr "Modifica Poly (Rimuovi Punto)" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Remove Polygon And Point" +msgstr "Rimuovi Poligono e Punto" + #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #: editor/plugins/animation_player_editor_plugin.cpp @@ -4413,6 +4420,16 @@ msgid "Move CanvasItem" msgstr "Modifica CanvasItem" #: editor/plugins/canvas_item_editor_plugin.cpp +msgid "Presets for the anchors and margins values of a Control node." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp +msgid "" +"Children of containers have their anchors and margins values overridden by " +"their parent." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp msgid "Anchors only" msgstr "Solo ancore" @@ -5345,6 +5362,12 @@ msgid "Create UV Map" msgstr "Crea UV Map" #: editor/plugins/polygon_2d_editor_plugin.cpp +msgid "" +"Polygon 2D has internal vertices, so it can no longer be edited in the " +"viewport." +msgstr "" + +#: editor/plugins/polygon_2d_editor_plugin.cpp #, fuzzy msgid "Create Polygon & UV" msgstr "Crea Poly" @@ -6488,7 +6511,7 @@ msgid "Post" msgstr "Post" #: editor/plugins/spatial_editor_plugin.cpp -msgid "Name-less gizmo" +msgid "Nameless gizmo" msgstr "" #: editor/plugins/sprite_editor_plugin.cpp @@ -6571,10 +6594,16 @@ msgid "(empty)" msgstr "(vuoto)" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animations" +#, fuzzy +msgid "Animations:" msgstr "Animazioni" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "New Animation" +msgstr "Animazione" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed (FPS):" msgstr "Velocità (FPS):" @@ -6583,7 +6612,8 @@ msgid "Loop" msgstr "Loop" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animation Frames" +#, fuzzy +msgid "Animation Frames:" msgstr "Frames Animazione" #: editor/plugins/sprite_frames_editor_plugin.cpp @@ -7433,6 +7463,19 @@ msgstr "Sei sicuro di voler aprire più di un progetto?" #: editor/project_manager.cpp msgid "" +"The following project settings file does not specify the version of Godot " +"through which it was created.\n" +"\n" +"%s\n" +"\n" +"If you proceed with opening it, it will be converted to Godot's current " +"configuration file format.\n" +"Warning: You will not be able to open the project with previous versions of " +"the engine anymore." +msgstr "" + +#: editor/project_manager.cpp +msgid "" "The following project settings file was generated by an older engine " "version, and needs to be converted for this version:\n" "\n" @@ -9045,11 +9088,6 @@ msgstr "Progetto" #: modules/mono/editor/mono_bottom_panel.cpp #, fuzzy -msgid "Warnings" -msgstr "Avvertimento" - -#: modules/mono/editor/mono_bottom_panel.cpp -#, fuzzy msgid "View log" msgstr "Vedi Files" @@ -9765,6 +9803,13 @@ msgstr "" "Il nodo ParallaxLayer funziona solamente quando impostato come figlio di un " "nodo ParallaxBackground." +#: scene/2d/particles_2d.cpp +msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles2D node instead. You can use the \"Convert to " +"CPUParticles\" option for this purpose." +msgstr "" + #: scene/2d/particles_2d.cpp scene/3d/particles.cpp msgid "" "A material to process the particles is not assigned, so no behavior is " @@ -9954,6 +9999,13 @@ msgstr "" #: scene/3d/particles.cpp msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles node instead. You can use the \"Convert to CPUParticles" +"\" option for this purpose." +msgstr "" + +#: scene/3d/particles.cpp +msgid "" "Nothing is visible because meshes have not been assigned to draw passes." msgstr "Nulla é visibile perché le mesh non sono state assegnate ai draw pass." @@ -9992,23 +10044,6 @@ msgstr "" "La proprietà path deve puntare ad un nodo Spaziale (Spatial) valido per " "poter funzionare." -#: scene/3d/scenario_fx.cpp -msgid "WorldEnvironment needs an Environment resource." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." -msgstr "" -"Solamente un WorldEnvironment è consentito per scena (o insieme di scene " -"istanziate)." - -#: scene/3d/scenario_fx.cpp -msgid "" -"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " -"this environment's Background Mode to Canvas (for 2D scenes)." -msgstr "" - #: scene/3d/soft_body.cpp msgid "This body will be ignored until you set a mesh" msgstr "" @@ -10040,6 +10075,23 @@ msgstr "" "VehicleWheel serve a provvedere un sistema di ruote a VehicleBody. Per " "favore usalo come figlio di VehicleBody." +#: scene/3d/world_environment.cpp +msgid "WorldEnvironment needs an Environment resource." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." +msgstr "" +"Solamente un WorldEnvironment è consentito per scena (o insieme di scene " +"istanziate)." + +#: scene/3d/world_environment.cpp +msgid "" +"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " +"this environment's Background Mode to Canvas (for 2D scenes)." +msgstr "" + #: scene/animation/animation_blend_tree.cpp msgid "On BlendTree node '%s', animation not found: '%s'" msgstr "" @@ -10087,12 +10139,21 @@ msgid "This node has been deprecated. Use AnimationTree instead." msgstr "" #: scene/gui/color_picker.cpp +msgid "Pick a color from the screen." +msgstr "" + +#: scene/gui/color_picker.cpp #, fuzzy msgid "Raw Mode" msgstr "Modalità di Pan" #: scene/gui/color_picker.cpp -msgid "Add current color as a preset" +msgid "Switch between hexadecimal and code values." +msgstr "" + +#: scene/gui/color_picker.cpp +#, fuzzy +msgid "Add current color as a preset." msgstr "Aggiungi colore attuale come preset" #: scene/gui/dialogs.cpp @@ -10191,6 +10252,19 @@ msgid "Varyings can only be assigned in vertex function." msgstr "" #, fuzzy +#~ msgid "Warnings:" +#~ msgstr "Avvertimento" + +#~ msgid "Font Size:" +#~ msgstr "Dimensione Font:" + +#~ msgid "Line:" +#~ msgstr "Riga:" + +#~ msgid "Col:" +#~ msgstr "Col:" + +#, fuzzy #~ msgid "OrientedPathFollow only works when set as a child of a Path node." #~ msgstr "" #~ "PathFollow2D funziona solamente quando impostato come figlio di un nodo " diff --git a/editor/translations/ja.po b/editor/translations/ja.po index 20966bda3a..863ed46ae1 100644 --- a/editor/translations/ja.po +++ b/editor/translations/ja.po @@ -18,15 +18,15 @@ # sugusan <sugusan.development@gmail.com>, 2018. # Nathan Lovato <nathan.lovato.art@gmail.com>, 2018. # nyanode <akaruooyagi@yahoo.co.jp>, 2018. -# nitenook <admin@alterbaum.net>, 2018. +# nitenook <admin@alterbaum.net>, 2018, 2019. # Rob Matych <robertsmatych@gmail.com>, 2018. # Hidetsugu Takahashi <manzyun@gmail.com>, 2019. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2019-01-19 19:21+0000\n" -"Last-Translator: Hidetsugu Takahashi <manzyun@gmail.com>\n" +"PO-Revision-Date: 2019-02-18 08:54+0000\n" +"Last-Translator: nitenook <admin@alterbaum.net>\n" "Language-Team: Japanese <https://hosted.weblate.org/projects/godot-engine/" "godot/ja/>\n" "Language: ja\n" @@ -34,7 +34,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Weblate 3.4-dev\n" +"X-Generator: Weblate 3.5-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -474,7 +474,7 @@ msgstr "ã™ã¹ã¦ã®ã‚¢ãƒ‹ãƒ¡ãƒ¼ã‚·ãƒ§ãƒ³ã‚’クリーンアップ" #: editor/animation_track_editor.cpp msgid "Clean-Up Animation(s) (NO UNDO!)" -msgstr "アニメーションをクリーンアップ(アンドゥä¸å¯ï¼ï¼‰" +msgstr "ã‚¢ãƒ‹ãƒ¡ãƒ¼ã‚·ãƒ§ãƒ³ã‚’ã‚¯ãƒªãƒ¼ãƒ³ã‚¢ãƒƒãƒ—ï¼ˆã€Œå…ƒã«æˆ»ã™ã€ä¸å¯!)" #: editor/animation_track_editor.cpp msgid "Clean-Up" @@ -560,21 +560,14 @@ msgstr "ズームアウト" msgid "Reset Zoom" msgstr "ズームをリセット" -#: editor/code_editor.cpp -msgid "Warnings:" -msgstr "è¦å‘Š:" - -#: editor/code_editor.cpp -msgid "Font Size:" -msgstr "フォントサイズ:" - -#: editor/code_editor.cpp -msgid "Line:" -msgstr "行:" +#: editor/code_editor.cpp modules/mono/editor/mono_bottom_panel.cpp +msgid "Warnings" +msgstr "è¦å‘Š" #: editor/code_editor.cpp -msgid "Col:" -msgstr "列:" +#, fuzzy +msgid "Line and column numbers." +msgstr "行åŠã³åˆ—番å·" #: editor/connections_dialog.cpp msgid "Method in target Node must be specified!" @@ -676,7 +669,7 @@ msgstr "ã‚·ã‚°ãƒŠãƒ«ã®æŽ¥ç¶š: " #: editor/connections_dialog.cpp msgid "Edit Connection: " -msgstr "接続を編集 " +msgstr "接続を編集: " #: editor/connections_dialog.cpp msgid "Are you sure you want to remove all connections from the \"%s\" signal?" @@ -813,7 +806,7 @@ msgstr "次ã®ã‚ªãƒ¼ãƒŠãƒ¼:" #: editor/dependency_editor.cpp msgid "Remove selected files from the project? (no undo)" -msgstr "é¸æŠžã—ãŸãƒ•ァイルをプãƒã‚¸ã‚§ã‚¯ãƒˆã‹ã‚‰é™¤åŽ»ã—ã¾ã™ã‹ï¼Ÿï¼ˆã‚¢ãƒ³ãƒ‰ã‚¥ä¸å¯ï¼‰" +msgstr "é¸æŠžã—ãŸãƒ•ァイルをプãƒã‚¸ã‚§ã‚¯ãƒˆã‹ã‚‰é™¤åŽ»ã—ã¾ã™ã‹ï¼Ÿï¼ˆã€Œå…ƒã«æˆ»ã™ã€ä¸å¯ï¼‰" #: editor/dependency_editor.cpp msgid "" @@ -822,7 +815,7 @@ msgid "" "Remove them anyway? (no undo)" msgstr "" "除去ã—よã†ã¨ã—ã¦ã„るファイルã¯ä»–ã®ãƒªã‚½ãƒ¼ã‚¹ã®å‹•作ã«å¿…è¦ã§ã™ã€‚\n" -"無視ã—ã¦é™¤åŽ»ã—ã¾ã™ã‹ï¼Ÿï¼ˆã‚¢ãƒ³ãƒ‰ã‚¥ä¸å¯ï¼‰" +"無視ã—ã¦é™¤åŽ»ã—ã¾ã™ã‹ï¼Ÿï¼ˆã€Œå…ƒã«æˆ»ã™ã€ä¸å¯ï¼‰" #: editor/dependency_editor.cpp editor/export_template_manager.cpp msgid "Cannot remove:" @@ -854,7 +847,7 @@ msgstr "èªã¿è¾¼ã¿ã‚¨ãƒ©ãƒ¼ï¼" #: editor/dependency_editor.cpp msgid "Permanently delete %d item(s)? (No undo!)" -msgstr "%d 個ã®ã‚¢ã‚¤ãƒ†ãƒ を完全ã«å‰Šé™¤ã—ã¾ã™ã‹ï¼Ÿï¼ˆã‚¢ãƒ³ãƒ‰ã‚¥ä¸å¯ï¼‰" +msgstr "%d 個ã®ã‚¢ã‚¤ãƒ†ãƒ を完全ã«å‰Šé™¤ã—ã¾ã™ã‹?ï¼ˆã€Œå…ƒã«æˆ»ã™ã€ä¸å¯!)" #: editor/dependency_editor.cpp msgid "Owns" @@ -866,7 +859,7 @@ msgstr "æ‰€æœ‰æ¨©ãŒæ˜Žç¤ºã•れã¦ã„ãªã„リソース:" #: editor/dependency_editor.cpp editor/editor_node.cpp msgid "Orphan Resource Explorer" -msgstr "å¤ç«‹ãƒªã‚½ãƒ¼ã‚¹ç”¨ã‚¨ã‚¯ã‚¹ãƒ—ãƒãƒ¼ãƒ©ãƒ¼" +msgstr "å¤ç«‹ãƒªã‚½ãƒ¼ã‚¹ エクスプãƒãƒ¼ãƒ©ãƒ¼" #: editor/dependency_editor.cpp msgid "Delete selected files?" @@ -875,8 +868,8 @@ msgstr "é¸æŠžã—ãŸãƒ•ァイルを削除ã—ã¾ã™ã‹ï¼Ÿ" #: editor/dependency_editor.cpp editor/editor_audio_buses.cpp #: editor/editor_file_dialog.cpp editor/editor_node.cpp #: editor/filesystem_dock.cpp editor/plugins/item_list_editor_plugin.cpp -#: editor/project_export.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_dock.cpp +#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp +#: editor/project_settings_editor.cpp editor/scene_tree_dock.cpp msgid "Delete" msgstr "削除" @@ -984,9 +977,8 @@ msgid "Uncompressing Assets" msgstr "アセットを展開" #: editor/editor_asset_installer.cpp editor/project_manager.cpp -#, fuzzy msgid "Package installed successfully!" -msgstr "パッケージã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã«æˆåŠŸã—ã¾ã—ãŸï¼" +msgstr "パッケージã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã«æˆåŠŸã—ã¾ã—ãŸ!" #: editor/editor_asset_installer.cpp #: editor/plugins/asset_library_editor_plugin.cpp @@ -1132,8 +1124,9 @@ msgid "Add Bus" msgstr "ãƒã‚¹ã‚’è¿½åŠ " #: editor/editor_audio_buses.cpp -msgid "Create a new Bus Layout." -msgstr "æ–°è¦ãƒã‚¹ãƒ¬ã‚¤ã‚¢ã‚¦ãƒˆã‚’作æˆã€‚" +#, fuzzy +msgid "Add a new Audio Bus to this layout." +msgstr "オーディオãƒã‚¹ã®ãƒ¬ã‚¤ã‚¢ã‚¦ãƒˆã‚’別åã§ä¿å˜..." #: editor/editor_audio_buses.cpp editor/editor_properties.cpp #: editor/plugins/animation_player_editor_plugin.cpp editor/property_editor.cpp @@ -1161,6 +1154,10 @@ msgstr "デフォルトをèªè¾¼ã‚€" msgid "Load the default Bus Layout." msgstr "デフォルトã®ãƒã‚¹ãƒ¬ã‚¤ã‚¢ã‚¦ãƒˆã‚’èªè¾¼ã¿ã¾ã™ã€‚" +#: editor/editor_audio_buses.cpp +msgid "Create a new Bus Layout." +msgstr "æ–°è¦ãƒã‚¹ãƒ¬ã‚¤ã‚¢ã‚¦ãƒˆã‚’作æˆã€‚" + #: editor/editor_autoload_settings.cpp msgid "Invalid name." msgstr "無効ãªåå‰ã§ã™ã€‚" @@ -1297,11 +1294,8 @@ msgid "Storing File:" msgstr "ファイルã®ä¿å˜:" #: editor/editor_export.cpp -#, fuzzy msgid "No export template found at the expected path:" -msgstr "" -"エクスãƒãƒ¼ãƒˆã™ã‚‹ãƒ†ãƒ³ãƒ—レートãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“.\n" -"ダウンãƒãƒ¼ãƒ‰ã—ã¦ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã—ã¦ãã ã•ã„." +msgstr "エクスãƒãƒ¼ãƒˆ テンプレートãŒäºˆæƒ³ã•れãŸãƒ‘スã«è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“:" #: editor/editor_export.cpp msgid "Packing" @@ -1310,16 +1304,14 @@ msgstr "パックã™ã‚‹" #: editor/editor_export.cpp platform/android/export/export.cpp #: platform/iphone/export/export.cpp platform/javascript/export/export.cpp #: platform/osx/export/export.cpp platform/uwp/export/export.cpp -#, fuzzy msgid "Custom debug template not found." -msgstr "カスタム デãƒãƒƒã‚°ãƒ‘ッケージãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“" +msgstr "カスタムデãƒãƒƒã‚°ãƒ†ãƒ³ãƒ—レートãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。" #: editor/editor_export.cpp platform/android/export/export.cpp #: platform/iphone/export/export.cpp platform/javascript/export/export.cpp #: platform/osx/export/export.cpp platform/uwp/export/export.cpp -#, fuzzy msgid "Custom release template not found." -msgstr "カスタム リリースパッケージãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“." +msgstr "カスタムリリーステンプレートãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。" #: editor/editor_export.cpp platform/javascript/export/export.cpp msgid "Template file not found:" @@ -1930,7 +1922,7 @@ msgstr "å…ƒã«æˆ»ã™" #: editor/editor_node.cpp msgid "This action cannot be undone. Revert anyway?" -msgstr "ã“ã®æ“作ã¯ã‚¢ãƒ³ãƒ‰ã‚¥ã§ãã¾ã›ã‚“。ãれã§ã‚‚å…ƒã«æˆ»ã—ã¾ã™ã‹ï¼Ÿ" +msgstr "ã“ã®æ“作ã¯ã€Œå…ƒã«æˆ»ã™ã€ã¯ã§ãã¾ã›ã‚“。ãれã§ã‚‚å…ƒã«æˆ»ã—ã¾ã™ã‹ï¼Ÿ" #: editor/editor_node.cpp msgid "Quick Run Scene..." @@ -2394,7 +2386,7 @@ msgstr "カスタムシーンを実行" #: editor/editor_node.cpp msgid "Changing the video driver requires restarting the editor." -msgstr "ビデオドライãƒã‚’変更ã™ã‚‹ã«ã¯ã€ã‚¨ãƒ‡ã‚£ã‚¿ã‚’å†èµ·å‹•ã™ã‚‹å¿…è¦ãŒã‚りã¾ã™ã€‚" +msgstr "ビデオドライãƒã®å¤‰æ›´ã«ã¯ã‚¨ãƒ‡ã‚£ã‚¿ã®å†èµ·å‹•ãŒå¿…è¦ã§ã™ã€‚" #: editor/editor_node.cpp editor/project_settings_editor.cpp #: editor/settings_config_dialog.cpp @@ -2402,7 +2394,8 @@ msgid "Save & Restart" msgstr "ä¿å˜ã—ã¦å†èµ·å‹•" #: editor/editor_node.cpp -msgid "Spins when the editor window repaints!" +#, fuzzy +msgid "Spins when the editor window redraws." msgstr "エディタウィンドウã®å†æç”»æ™‚ã«ã‚¹ãƒ”ンã—ã¾ã™ï¼" #: editor/editor_node.cpp @@ -2609,14 +2602,12 @@ msgid "[Empty]" msgstr "[空]" #: editor/editor_properties.cpp editor/plugins/root_motion_editor_plugin.cpp -#, fuzzy msgid "Assign..." -msgstr "アサイン.." +msgstr "割り当ã¦.." #: editor/editor_properties.cpp -#, fuzzy msgid "Invalid RID" -msgstr "無効ãªãƒ‘ス" +msgstr "無効㪠RID" #: editor/editor_properties.cpp msgid "" @@ -3175,7 +3166,7 @@ msgstr "ç½®æ›: " #: editor/find_in_files.cpp msgid "Replace all (no undo)" -msgstr "ã™ã¹ã¦ç½®æ›ï¼ˆã‚¢ãƒ³ãƒ‰ã‚¥ä¸å¯ï¼‰" +msgstr "ã™ã¹ã¦ç½®æ›ï¼ˆã€Œå…ƒã«æˆ»ã™ã€ä¸å¯ï¼‰" #: editor/find_in_files.cpp msgid "Searching..." @@ -3327,9 +3318,8 @@ msgid "Save scenes, re-import and restart" msgstr "" #: editor/import_dock.cpp -#, fuzzy msgid "Changing the type of an imported file requires editor restart." -msgstr "ビデオドライãƒã‚’変更ã™ã‚‹ã«ã¯ã€ã‚¨ãƒ‡ã‚£ã‚¿ã‚’å†èµ·å‹•ã™ã‚‹å¿…è¦ãŒã‚りã¾ã™ã€‚" +msgstr "インãƒãƒ¼ãƒˆã—ãŸãƒ•ァイルã®ã‚¿ã‚¤ãƒ—ã®å¤‰æ›´ã«ã¯ã‚¨ãƒ‡ã‚£ã‚¿ã®å†èµ·å‹•ãŒå¿…è¦ã§ã™ã€‚" #: editor/import_dock.cpp msgid "" @@ -3390,9 +3380,8 @@ msgid "Load an existing resource from disk and edit it." msgstr "æ—¢å˜ã®ãƒªã‚½ãƒ¼ã‚¹ã‚’ディスクã‹ã‚‰èªè¾¼ã¿ç·¨é›†ã™ã‚‹ã€‚" #: editor/inspector_dock.cpp -#, fuzzy msgid "Save the currently edited resource." -msgstr "ç¾åœ¨ç·¨é›†ä¸ã®ãƒªã‚½ãƒ¼ã‚¹ã‚’ä¿å˜ã™ã‚‹" +msgstr "ç¾åœ¨ç·¨é›†ä¸ã®ãƒªã‚½ãƒ¼ã‚¹ã‚’ä¿å˜ã™ã‚‹ã€‚" #: editor/inspector_dock.cpp msgid "Go to the previous edited object in history." @@ -3460,22 +3449,6 @@ msgid "Create Polygon" msgstr "ãƒãƒªã‚´ãƒ³ã‚’生æˆ" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Edit Polygon" -msgstr "ãƒãƒªã‚´ãƒ³ã‚’編集" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Insert Point" -msgstr "ãƒã‚¤ãƒ³ãƒˆæŒ¿å…¥" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Edit Polygon (Remove Point)" -msgstr "ãƒãƒªã‚´ãƒ³ã‚’編集(点を除去)" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Remove Polygon And Point" -msgstr "ãƒãƒªã‚´ãƒ³ã¨ç‚¹ã‚’除去" - -#: editor/plugins/abstract_polygon_2d_editor.cpp #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp msgid "Create points." @@ -3496,6 +3469,22 @@ msgstr "" msgid "Erase points." msgstr "点を消ã™ã€‚" +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Edit Polygon" +msgstr "ãƒãƒªã‚´ãƒ³ã‚’編集" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Insert Point" +msgstr "ãƒã‚¤ãƒ³ãƒˆæŒ¿å…¥" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Edit Polygon (Remove Point)" +msgstr "ãƒãƒªã‚´ãƒ³ã‚’編集(点を除去)" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Remove Polygon And Point" +msgstr "ãƒãƒªã‚´ãƒ³ã¨ç‚¹ã‚’除去" + #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #: editor/plugins/animation_player_editor_plugin.cpp @@ -3508,9 +3497,8 @@ msgstr "ã‚¢ãƒ‹ãƒ¡ãƒ¼ã‚·ãƒ§ãƒ³ã‚’è¿½åŠ " #: editor/plugins/animation_blend_space_2d_editor.cpp #: editor/plugins/animation_blend_tree_editor_plugin.cpp #: editor/plugins/animation_state_machine_editor.cpp -#, fuzzy msgid "Load..." -msgstr "èªè¾¼ã‚€.." +msgstr "èªã¿è¾¼ã‚€.." #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp @@ -3890,9 +3878,8 @@ msgid "Connect nodes." msgstr "ノードを接続。" #: editor/plugins/animation_state_machine_editor.cpp -#, fuzzy msgid "Remove selected node or transition." -msgstr "é¸æŠžã—ãŸãƒŽãƒ¼ãƒ‰ã¾ãŸã¯ãƒˆãƒ©ãƒ³ã‚¸ã‚·ãƒ§ãƒ³ã‚’除去" +msgstr "é¸æŠžã—ãŸãƒŽãƒ¼ãƒ‰ã¾ãŸã¯ãƒˆãƒ©ãƒ³ã‚¸ã‚·ãƒ§ãƒ³ã‚’除去。" #: editor/plugins/animation_state_machine_editor.cpp #, fuzzy @@ -4297,6 +4284,16 @@ msgid "Move CanvasItem" msgstr "CanvasItemを移動" #: editor/plugins/canvas_item_editor_plugin.cpp +msgid "Presets for the anchors and margins values of a Control node." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp +msgid "" +"Children of containers have their anchors and margins values overridden by " +"their parent." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp msgid "Anchors only" msgstr "アンカーã®ã¿" @@ -4309,9 +4306,8 @@ msgid "Change Anchors" msgstr "アンカーを変更" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Paste Pose" -msgstr "ãƒãƒ¼ã‚ºã‚’貼り付ã‘ã‚‹" +msgstr "ãƒãƒ¼ã‚ºã‚’貼り付ã‘" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "" @@ -4451,14 +4447,12 @@ msgid "Unlock the selected object (can be moved)." msgstr "é¸æŠžã—ãŸã‚ªãƒ–ジェクトをアンãƒãƒƒã‚¯ (移動å¯èƒ½ã«ã™ã‚‹)。" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Makes sure the object's children are not selectable." -msgstr "ã“ã®ã‚ªãƒ–ジェクトã®åï¼ˆã‚ªãƒ–ã‚¸ã‚§ã‚¯ãƒˆï¼‰ã‚’é¸æŠžä¸å¯ã¨ã™ã‚‹." +msgstr "オブジェクトã®åã‚’é¸æŠžä¸å¯ã«ã™ã‚‹ã€‚" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Restores the object's children's ability to be selected." -msgstr "ã“ã®ã‚ªãƒ–ジェクトã®åï¼ˆã‚ªãƒ–ã‚¸ã‚§ã‚¯ãƒˆï¼‰ã‚’é¸æŠžå¯èƒ½ã¨ã™ã‚‹." +msgstr "オブジェクトã®åã‚’é¸æŠžå¯èƒ½ã«æˆ»ã™ã€‚" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Skeleton Options" @@ -4481,9 +4475,8 @@ msgid "Make Custom Bone(s) from Node(s)" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Clear Custom Bones" -msgstr "ボーンをクリアã™ã‚‹" +msgstr "カスタムボーンをクリア" #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp @@ -4711,12 +4704,10 @@ msgid "Item List Editor" msgstr "アイテムリストã®ã‚¨ãƒ‡ã‚£ã‚¿" #: editor/plugins/light_occluder_2d_editor_plugin.cpp -#, fuzzy msgid "Create Occluder Polygon" -msgstr "オクルージョンを生ã˜ã‚‹ãƒãƒªã‚´ãƒ³ã‚’生æˆ" +msgstr "オクルーダーãƒãƒªã‚´ãƒ³ã‚’生æˆ" #: editor/plugins/mesh_instance_editor_plugin.cpp -#, fuzzy msgid "Mesh is empty!" msgstr "メッシュãŒã‚りã¾ã›ã‚“!" @@ -5238,9 +5229,8 @@ msgid "Split Segment (in curve)" msgstr "分割ã™ã‚‹(曲線を)" #: editor/plugins/physical_bone_plugin.cpp -#, fuzzy msgid "Move joint" -msgstr "ãƒã‚¤ãƒ³ãƒˆã‚’移動" +msgstr "ジョイントを移動" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "" @@ -5248,9 +5238,8 @@ msgid "" msgstr "" #: editor/plugins/polygon_2d_editor_plugin.cpp -#, fuzzy msgid "Sync Bones" -msgstr "ボーンを表示ã™ã‚‹" +msgstr "ãƒœãƒ¼ãƒ³ã‚’åŒæœŸ" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "" @@ -5265,32 +5254,34 @@ msgid "Create UV Map" msgstr "UVマップを生æˆ" #: editor/plugins/polygon_2d_editor_plugin.cpp +msgid "" +"Polygon 2D has internal vertices, so it can no longer be edited in the " +"viewport." +msgstr "" + +#: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Create Polygon & UV" msgstr "ãƒãƒªã‚´ãƒ³ã¨UVを生æˆ" #: editor/plugins/polygon_2d_editor_plugin.cpp -#, fuzzy msgid "Create Internal Vertex" -msgstr "水平ガイドを作æˆ" +msgstr "å†…éƒ¨é ‚ç‚¹ã‚’ä½œæˆ" #: editor/plugins/polygon_2d_editor_plugin.cpp -#, fuzzy msgid "Remove Internal Vertex" -msgstr "曲線ã®In-ãƒãƒ³ãƒ‰ãƒ«ã‚’除去" +msgstr "å†…éƒ¨é ‚ç‚¹ã‚’é™¤åŽ»" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Invalid Polygon (need 3 different vertices)" -msgstr "" +msgstr "無効ãªãƒãƒªã‚´ãƒ³ (3ã¤ã®ç•°ãªã‚‹é ‚点ãŒå¿…è¦ã§ã™)" #: editor/plugins/polygon_2d_editor_plugin.cpp -#, fuzzy msgid "Add Custom Polygon" -msgstr "ãƒãƒªã‚´ãƒ³ã‚’編集" +msgstr "カスタムãƒãƒªã‚´ãƒ³ã‚’è¿½åŠ " #: editor/plugins/polygon_2d_editor_plugin.cpp -#, fuzzy msgid "Remove Custom Polygon" -msgstr "ãƒãƒªã‚´ãƒ³ã¨ç‚¹ã‚’除去" +msgstr "カスタムãƒãƒªã‚´ãƒ³ã‚’除去" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Transform UV Map" @@ -5442,9 +5433,8 @@ msgid "Sync Bones to Polygon" msgstr "ãƒãƒªã‚´ãƒ³ã®ç¸®å°ºã‚’変更" #: editor/plugins/resource_preloader_editor_plugin.cpp -#, fuzzy msgid "ERROR: Couldn't load resource!" -msgstr "エラー:リソースをèªã¿è¾¼ã‚ã¾ã›ã‚“ã§ã—ãŸ!" +msgstr "エラー: リソースをèªã¿è¾¼ã‚ã¾ã›ã‚“ã§ã—ãŸ!" #: editor/plugins/resource_preloader_editor_plugin.cpp msgid "Add Resource" @@ -5500,9 +5490,8 @@ msgid "AnimationTree has no path set to an AnimationPlayer" msgstr "" #: editor/plugins/root_motion_editor_plugin.cpp -#, fuzzy msgid "Path to AnimationPlayer is invalid" -msgstr "アニメーションツリーã«å•題ãŒã‚りã¾ã™." +msgstr "AnimationPlayer ã¸ã®ãƒ‘スãŒç„¡åйã§ã™" #: editor/plugins/script_editor_plugin.cpp #, fuzzy @@ -6408,7 +6397,7 @@ msgid "Post" msgstr "" #: editor/plugins/spatial_editor_plugin.cpp -msgid "Name-less gizmo" +msgid "Nameless gizmo" msgstr "" #: editor/plugins/sprite_editor_plugin.cpp @@ -6489,8 +6478,12 @@ msgid "(empty)" msgstr "(空)" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animations" -msgstr "アニメーション" +msgid "Animations:" +msgstr "アニメーション:" + +#: editor/plugins/sprite_frames_editor_plugin.cpp +msgid "New Animation" +msgstr "æ–°è¦ã‚¢ãƒ‹ãƒ¡ãƒ¼ã‚·ãƒ§ãƒ³" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed (FPS):" @@ -6501,8 +6494,8 @@ msgid "Loop" msgstr "ループ" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animation Frames" -msgstr "アニメーションã®ãƒ•レーム" +msgid "Animation Frames:" +msgstr "アニメーション フレーム:" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Insert Empty (Before)" @@ -6829,9 +6822,8 @@ msgid "Erase bitmask." msgstr "点を消ã™ã€‚" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Create a new polygon." -msgstr "æ–°è¦ã«ãƒãƒªã‚´ãƒ³ã‚’生æˆã™ã‚‹" +msgstr "æ–°è¦ãƒãƒªã‚´ãƒ³ã‚’生æˆã€‚" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Keep polygon inside region Rect." @@ -6846,9 +6838,10 @@ msgid "Display Tile Names (Hold Alt Key)" msgstr "タイルåを表示 (Altã‚ーを長押ã—)" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Remove selected texture? This will remove all tiles which use it." -msgstr "パスã®ãƒã‚¤ãƒ³ãƒˆã‚’除去" +msgstr "" +"é¸æŠžã—ãŸãƒ†ã‚¯ã‚¹ãƒãƒ£ã‚’除去ã—ã¾ã™ã‹? ã“れを使用ã—ã¦ã„ã‚‹ã™ã¹ã¦ã®ã‚¿ã‚¤ãƒ«ã¯é™¤åŽ»ã•れ" +"ã¾ã™ã€‚" #: editor/plugins/tile_set_editor_plugin.cpp msgid "You haven't selected a texture to remove." @@ -6928,18 +6921,16 @@ msgid "Set Tile Region" msgstr "テクスãƒãƒ£ã€€ãƒªãƒ¼ã‚¸ãƒ§ãƒ³" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Create Tile" -msgstr "フォルダーを作æˆ" +msgstr "タイルを生æˆ" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Set Tile Icon" -msgstr "" +msgstr "タイル アイコンをè¨å®š" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Edit Tile Bitmask" -msgstr "フィルタã®ç·¨é›†" +msgstr "タイル ビットマスクを編集" #: editor/plugins/tile_set_editor_plugin.cpp #, fuzzy @@ -6947,28 +6938,24 @@ msgid "Edit Collision Polygon" msgstr "æ—¢å˜ã®ãƒãƒªã‚´ãƒ³ã‚’編集:" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Edit Occlusion Polygon" -msgstr "ãƒãƒªã‚´ãƒ³ã‚’編集" +msgstr "オクルージョン ãƒãƒªã‚´ãƒ³ã‚’編集" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Edit Navigation Polygon" -msgstr "ナビゲーションãƒãƒªã‚´ãƒ³ã‚’生æˆ" +msgstr "ナビゲーション ãƒãƒªã‚´ãƒ³ã‚’編集" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Paste Tile Bitmask" -msgstr "ビットマスクを貼り付ã‘。" +msgstr "タイル ビットマスクを貼り付ã‘" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Clear Tile Bitmask" -msgstr "" +msgstr "タイル ビットマスクをクリア" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Remove Tile" -msgstr "テンプレートを除去" +msgstr "タイルを除去" #: editor/plugins/tile_set_editor_plugin.cpp #, fuzzy @@ -6976,38 +6963,32 @@ msgid "Remove Collision Polygon" msgstr "ãƒãƒªã‚´ãƒ³ã¨ç‚¹ã‚’除去" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Remove Occlusion Polygon" -msgstr "オクルージョンを生ã˜ã‚‹ãƒãƒªã‚´ãƒ³ã‚’生æˆ" +msgstr "オクルージョン ãƒãƒªã‚´ãƒ³ã‚’除去" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Remove Navigation Polygon" -msgstr "ナビゲーションãƒãƒªã‚´ãƒ³ã‚’生æˆ" +msgstr "ナビゲーション ãƒãƒªã‚´ãƒ³ã‚’除去" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Edit Tile Priority" -msgstr "フィルタã®ç·¨é›†" +msgstr "タイル プãƒãƒ‘ティを編集" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Edit Tile Z Index" msgstr "" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Create Collision Polygon" -msgstr "ナビゲーションãƒãƒªã‚´ãƒ³ã‚’生æˆ" +msgstr "コリジョン ãƒãƒªã‚´ãƒ³ã‚’生æˆ" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Create Occlusion Polygon" -msgstr "オクルージョンを生ã˜ã‚‹ãƒãƒªã‚´ãƒ³ã‚’生æˆ" +msgstr "オクルージョン ãƒãƒªã‚´ãƒ³ã‚’生æˆ" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "This property can't be changed." -msgstr "ã“ã®å‡¦ç†ã«ã¯ã‚·ãƒ¼ãƒ³ãŒå¿…è¦ã§ã™." +msgstr "ã“ã®ãƒ—ãƒãƒ‘ティã¯å¤‰æ›´ã§ãã¾ã›ã‚“。" #: editor/plugins/tile_set_editor_plugin.cpp #, fuzzy @@ -7133,19 +7114,16 @@ msgid "Feature List:" msgstr "メソッド一覧:" #: editor/project_export.cpp -#, fuzzy msgid "Script" -msgstr "æ–°è¦ã‚¹ã‚¯ãƒªãƒ—ト" +msgstr "スクリプト" #: editor/project_export.cpp -#, fuzzy msgid "Script Export Mode:" -msgstr "エクスãƒãƒ¼ãƒˆã®ãƒ¢ãƒ¼ãƒ‰:" +msgstr "スクリプトã®ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆãƒ¢ãƒ¼ãƒ‰:" #: editor/project_export.cpp -#, fuzzy msgid "Text" -msgstr "テクスãƒãƒ£" +msgstr "テã‚スト" #: editor/project_export.cpp #, fuzzy @@ -7169,9 +7147,8 @@ msgid "Export PCK/Zip" msgstr "PCK/Zipã®ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ" #: editor/project_export.cpp -#, fuzzy msgid "Export mode?" -msgstr "エクスãƒãƒ¼ãƒˆã®ãƒ¢ãƒ¼ãƒ‰:" +msgstr "エクスãƒãƒ¼ãƒˆ モード?" #: editor/project_export.cpp msgid "Export All" @@ -7233,21 +7210,20 @@ msgid "Invalid project path (changed anything?)." msgstr "䏿£ãªãƒ—ãƒã‚¸ã‚§ã‚¯ãƒˆã®ãƒ‘ス(何ã‹å¤‰ãˆã¾ã—ãŸã‹ï¼Ÿï¼‰" #: editor/project_manager.cpp -#, fuzzy msgid "" "Couldn't load project.godot in project path (error %d). It may be missing or " "corrupted." -msgstr "project.godotをプãƒã‚¸ã‚§ã‚¯ãƒˆãƒ‘スã«ç”Ÿæˆã§ãã¾ã›ã‚“ã§ã—ãŸ" +msgstr "" +"プãƒã‚¸ã‚§ã‚¯ãƒˆãƒ‘ス㮠project.godot ã‚’èªã¿è¾¼ã‚ã¾ã›ã‚“ã§ã—ãŸã€‚ (エラー %d)。見ã¤ã‹" +"らãªã„ã‹ç ´æã—ã¦ã„ã‚‹å¯èƒ½æ€§ãŒã‚りã¾ã™ã€‚" #: editor/project_manager.cpp -#, fuzzy msgid "Couldn't edit project.godot in project path." -msgstr "project.godotをプãƒã‚¸ã‚§ã‚¯ãƒˆãƒ‘スã«ç”Ÿæˆã§ãã¾ã›ã‚“ã§ã—ãŸ" +msgstr "プãƒã‚¸ã‚§ã‚¯ãƒˆãƒ‘ス㮠project.godot を編集ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚" #: editor/project_manager.cpp -#, fuzzy msgid "Couldn't create project.godot in project path." -msgstr "project.godotをプãƒã‚¸ã‚§ã‚¯ãƒˆãƒ‘スã«ç”Ÿæˆã§ãã¾ã›ã‚“ã§ã—ãŸ" +msgstr "project.godot をプãƒã‚¸ã‚§ã‚¯ãƒˆãƒ‘スã«ç”Ÿæˆã§ãã¾ã›ã‚“ã§ã—ãŸã€‚" #: editor/project_manager.cpp msgid "The following files failed extraction from package:" @@ -7307,11 +7283,11 @@ msgstr "å‚ç…§" #: editor/project_manager.cpp msgid "Renderer:" -msgstr "" +msgstr "レンダラー:" #: editor/project_manager.cpp msgid "OpenGL ES 3.0" -msgstr "" +msgstr "OpenGL ES 3.0" #: editor/project_manager.cpp msgid "" @@ -7320,10 +7296,14 @@ msgid "" "Incompatible with older hardware\n" "Not recommended for web games" msgstr "" +"高ã„ビジュアルクオリティ\n" +"ã™ã¹ã¦ã®æ©Ÿèƒ½ã‚’利用å¯èƒ½\n" +"å¤ã„ãƒãƒ¼ãƒ‰ã‚¦ã‚§ã‚¢ã¨ã®äº’æ›æ€§ãªã—\n" +"Webゲームã«ã¯éžæŽ¨å¥¨" #: editor/project_manager.cpp msgid "OpenGL ES 2.0" -msgstr "" +msgstr "OpenGL ES 2.0" #: editor/project_manager.cpp msgid "" @@ -7332,10 +7312,15 @@ msgid "" "Works on most hardware\n" "Recommended for web games" msgstr "" +"低ã„ビジュアルクオリティ\n" +"一部機能ã¯åˆ©ç”¨ä¸å¯\n" +"ã»ã¨ã‚“ã©ã®ãƒãƒ¼ãƒ‰ã‚¦ã‚§ã‚¢ã§å‹•作\n" +"Webã‚²ãƒ¼ãƒ ã«æŽ¨å¥¨" #: editor/project_manager.cpp msgid "Renderer can be changed later, but scenes may need to be adjusted." msgstr "" +"レンダラーã¯å¾Œã§å¤‰æ›´ã§ãã¾ã™ãŒã€ã‚·ãƒ¼ãƒ³ã®èª¿æ•´ãŒå¿…è¦ã¨ãªã‚‹å ´åˆãŒã‚りã¾ã™ã€‚" #: editor/project_manager.cpp msgid "Unnamed Project" @@ -7352,6 +7337,19 @@ msgstr "複数ã®ãƒ—ãƒã‚¸ã‚§ã‚¯ãƒˆã‚’é–‹ã„ã¦ã‚‚よã‚ã—ã„ã§ã™ã‹?" #: editor/project_manager.cpp msgid "" +"The following project settings file does not specify the version of Godot " +"through which it was created.\n" +"\n" +"%s\n" +"\n" +"If you proceed with opening it, it will be converted to Godot's current " +"configuration file format.\n" +"Warning: You will not be able to open the project with previous versions of " +"the engine anymore." +msgstr "" + +#: editor/project_manager.cpp +msgid "" "The following project settings file was generated by an older engine " "version, and needs to be converted for this version:\n" "\n" @@ -7361,6 +7359,13 @@ msgid "" "Warning: You will not be able to open the project with previous versions of " "the engine anymore." msgstr "" +"以下ã®ãƒ—ãƒã‚¸ã‚§ã‚¯ãƒˆè¨å®šãƒ•ァイルã¯ã€å¤ã„ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã®ã‚¨ãƒ³ã‚¸ãƒ³ã«ã‚ˆã‚Šç”Ÿæˆã•れã¦ãŠ" +"りã€ç¾åœ¨ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ç”¨ã«å¤‰æ›ãŒå¿…è¦ã§ã™:\n" +"\n" +"%s\n" +"\n" +"変æ›ã—ã¾ã™ã‹?\n" +"è¦å‘Š: プãƒã‚¸ã‚§ã‚¯ãƒˆã¯æ—§ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã®ã‚¨ãƒ³ã‚¸ãƒ³ã§é–‹ãã“ã¨ãŒã§ããªããªã‚Šã¾ã™ã€‚" #: editor/project_manager.cpp msgid "" @@ -7515,7 +7520,6 @@ msgid "Control+" msgstr "Control+" #: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp -#, fuzzy msgid "Press a Key..." msgstr "ã‚ーを押ã—ã¦ãã ã•ã„..." @@ -7980,14 +7984,12 @@ msgid "Case" msgstr "" #: editor/rename_dialog.cpp -#, fuzzy msgid "To Lowercase" -msgstr "å°æ–‡å—ã«ã™ã‚‹" +msgstr "å°æ–‡å—ã«" #: editor/rename_dialog.cpp -#, fuzzy msgid "To Uppercase" -msgstr "大文å—ã«ã™ã‚‹" +msgstr "大文å—ã«" #: editor/rename_dialog.cpp msgid "Reset" @@ -8120,7 +8122,6 @@ msgid "" msgstr "" #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Editable Children" msgstr "編集å¯èƒ½ãªå" @@ -8154,6 +8155,7 @@ msgid "Custom Node" msgstr "カスタムノード" #: editor/scene_tree_dock.cpp +#, fuzzy msgid "Can't operate on nodes from a foreign scene!" msgstr "ç•°ãªã‚‹ã‚·ãƒ¼ãƒ³ã®ãƒŽãƒ¼ãƒ‰ã‚’処ç†ã§ãã¾ã›ã‚“!" @@ -8266,14 +8268,13 @@ msgid "Local" msgstr "ãƒãƒ¼ã‚«ãƒ«" #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Clear Inheritance? (No Undo!)" -msgstr "継承をクリアã—ã¾ã™ã‹ï¼Ÿï¼ˆundoã§ãã¾ã›ã‚“!)" +msgstr "継承をクリアã—ã¾ã™ã‹?ï¼ˆã€Œå…ƒã«æˆ»ã™ã€ã§ãã¾ã›ã‚“!)" #: editor/scene_tree_editor.cpp #, fuzzy msgid "Toggle Visible" -msgstr "å¯è¦–性(Visibility)を変更" +msgstr "å¯è¦–性ã®åˆ‡ã‚Šæ›¿ãˆ" #: editor/scene_tree_editor.cpp #, fuzzy @@ -8281,22 +8282,20 @@ msgid "Node configuration warning:" msgstr "ノードã®è¨å®šã«é–¢ã™ã‚‹è¦å‘Š:" #: editor/scene_tree_editor.cpp -#, fuzzy msgid "" "Node has connection(s) and group(s).\n" "Click to show signals dock." msgstr "" -"ノードãŒã‚³ãƒã‚¯ã‚·ãƒ§ãƒ³ã¨ã‚°ãƒ«ãƒ¼ãƒ—ã‚’ä¿æŒã—ã¦ã„ã¾ã™\n" -"クリックã—ã¦ã‚·ã‚°ãƒŠãƒ«ãƒ‰ãƒƒã‚¯ã‚’表示ã—ã¦ãã ã•ã„" +"ãƒŽãƒ¼ãƒ‰ã«æŽ¥ç¶šã¨ã‚°ãƒ«ãƒ¼ãƒ—ãŒã‚りã¾ã™ã€‚\n" +"クリックã§ã‚·ã‚°ãƒŠãƒ« ドックを表示。" #: editor/scene_tree_editor.cpp -#, fuzzy msgid "" "Node has connections.\n" "Click to show signals dock." msgstr "" -"ノードã¯ã‚³ãƒã‚¯ã‚·ãƒ§ãƒ³ã‚’ä¿æŒã—ã¦ã„ã¾ã™\n" -"クリックã—ã¦ã‚·ã‚°ãƒŠãƒ«ãƒ‰ãƒƒã‚¯ã‚’表示ã—ã¦ãã ã•ã„" +"ãƒŽãƒ¼ãƒ‰ã«æŽ¥ç¶šãŒã‚りã¾ã™ã€‚\n" +"クリックã§ã‚·ã‚°ãƒŠãƒ« ドックを表示。" #: editor/scene_tree_editor.cpp #, fuzzy @@ -8329,9 +8328,8 @@ msgstr "" "クリックã—ã¦é¸æŠžå¯èƒ½ã«ã—ã¦ãã ã•ã„" #: editor/scene_tree_editor.cpp -#, fuzzy msgid "Toggle Visibility" -msgstr "å¯è¦–性(Visibility)を変更" +msgstr "å¯è¦–性ã®åˆ‡ã‚Šæ›¿ãˆ" #: editor/scene_tree_editor.cpp msgid "" @@ -8396,9 +8394,8 @@ msgid "Path is not local" msgstr "パスã¯ãƒãƒ¼ã‚«ãƒ«ã§ã¯ã‚りã¾ã›ã‚“" #: editor/script_create_dialog.cpp -#, fuzzy msgid "Invalid base path" -msgstr "䏿£ãªãƒ™ãƒ¼ã‚¹ï¼ˆbase)パス" +msgstr "無効ãªãƒ™ãƒ¼ã‚¹ パス" #: editor/script_create_dialog.cpp msgid "Directory of the same name exists" @@ -8699,18 +8696,16 @@ msgid "Platform" msgstr "プラットフォーム" #: modules/gdnative/gdnative_library_editor_plugin.cpp -#, fuzzy msgid "Dynamic Library" -msgstr "メッシュライブラリ..." +msgstr "ダイナミック ライブラリ" #: modules/gdnative/gdnative_library_editor_plugin.cpp msgid "Add an architecture entry" msgstr "" #: modules/gdnative/gdnative_library_editor_plugin.cpp -#, fuzzy msgid "GDNativeLibrary" -msgstr "メッシュライブラリ..." +msgstr "GDNative ライブラリ" #: modules/gdnative/gdnative_library_singleton_editor.cpp msgid "Library" @@ -8811,9 +8806,8 @@ msgid "GridMap Duplicate Selection" msgstr "é¸æŠžç¯„å›²ã‚’è¤‡è£½" #: modules/gridmap/grid_map_editor_plugin.cpp -#, fuzzy msgid "Grid Map" -msgstr "グリッドSnap" +msgstr "グリッドマップ" #: modules/gridmap/grid_map_editor_plugin.cpp #, fuzzy @@ -8901,9 +8895,8 @@ msgid "Fill Selection" msgstr "ã™ã¹ã¦é¸æŠž" #: modules/gridmap/grid_map_editor_plugin.cpp -#, fuzzy msgid "GridMap Settings" -msgstr "Snapã®è¨å®š" +msgstr "グリッドマップã®è¨å®š" #: modules/gridmap/grid_map_editor_plugin.cpp #, fuzzy @@ -8961,10 +8954,6 @@ msgid "Build Project" msgstr "プãƒã‚¸ã‚§ã‚¯ãƒˆã‚’ビルド" #: modules/mono/editor/mono_bottom_panel.cpp -msgid "Warnings" -msgstr "è¦å‘Š" - -#: modules/mono/editor/mono_bottom_panel.cpp msgid "View log" msgstr "ãƒã‚°ã‚’表示" @@ -9445,9 +9434,8 @@ msgid "Invalid public key for APK expansion." msgstr "" #: platform/android/export/export.cpp -#, fuzzy msgid "Invalid package name:" -msgstr "䏿£ãªã‚¯ãƒ©ã‚¹å" +msgstr "無効ãªãƒ‘ッケージå:" #: platform/iphone/export/export.cpp msgid "Identifier is missing." @@ -9458,9 +9446,8 @@ msgid "Identifier segments must be of non-zero length." msgstr "" #: platform/iphone/export/export.cpp -#, fuzzy msgid "The character '%s' is not allowed in Identifier." -msgstr "ã“ã®åå‰ã¯ä¸æ£ãªè˜åˆ¥åã§ã™:" +msgstr "æ–‡å— '%s' ã¯è˜åˆ¥åã«ä½¿ç”¨ã§ãã¾ã›ã‚“。" #: platform/iphone/export/export.cpp msgid "A digit cannot be the first character in a Identifier segment." @@ -9480,9 +9467,8 @@ msgid "App Store Team ID not specified - cannot configure the project." msgstr "" #: platform/iphone/export/export.cpp -#, fuzzy msgid "Invalid Identifier:" -msgstr "ã“ã®åå‰ã¯ä¸æ£ãªè˜åˆ¥åã§ã™:" +msgstr "無効ãªè˜åˆ¥å:" #: platform/iphone/export/export.cpp msgid "Required icon is not specified in the preset." @@ -9528,19 +9514,16 @@ msgid "Invalid package unique name." msgstr "無効ãªãƒ•ォント サイズã§ã™ã€‚" #: platform/uwp/export/export.cpp -#, fuzzy msgid "Invalid product GUID." -msgstr "無効ãªãƒ•ォント サイズã§ã™ã€‚" +msgstr "無効ãªãƒ—ãƒãƒ€ã‚¯ãƒˆ GUIDã§ã™ã€‚" #: platform/uwp/export/export.cpp -#, fuzzy msgid "Invalid publisher GUID." -msgstr "パブリッシャã®GUIDãŒä¸æ£ã§ã™." +msgstr "無効ãªãƒ‘ブリッシャー GUIDã§ã™ã€‚" #: platform/uwp/export/export.cpp -#, fuzzy msgid "Invalid background color." -msgstr "䏿£ãªèƒŒæ™¯è‰²" +msgstr "無効ãªèƒŒæ™¯è‰²ã§ã™ã€‚" #: platform/uwp/export/export.cpp #, fuzzy @@ -9683,6 +9666,13 @@ msgstr "" "ParallaxLayer ノードã¯ã€ParallaxBackground ノードã®åã¨ã—ã¦è¨å®šã•れã¦ã„ã‚‹å ´åˆ" "ã®ã¿å‹•作ã—ã¾ã™ã€‚" +#: scene/2d/particles_2d.cpp +msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles2D node instead. You can use the \"Convert to " +"CPUParticles\" option for this purpose." +msgstr "" + #: scene/2d/particles_2d.cpp scene/3d/particles.cpp #, fuzzy msgid "" @@ -9770,7 +9760,7 @@ msgstr "%d%%" #: scene/3d/baked_lightmap.cpp msgid "(Time Left: %d:%02d s)" -msgstr "" +msgstr "(Time Left: %d分%02dç§’)" #: scene/3d/baked_lightmap.cpp #, fuzzy @@ -9863,6 +9853,13 @@ msgstr "" "ã“れã¯ãƒŠãƒ“ゲーションデータã®ã¿æä¾›ã—ã¾ã™ã€‚" #: scene/3d/particles.cpp +msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles node instead. You can use the \"Convert to CPUParticles" +"\" option for this purpose." +msgstr "" + +#: scene/3d/particles.cpp #, fuzzy msgid "" "Nothing is visible because meshes have not been assigned to draw passes." @@ -9875,10 +9872,8 @@ msgid "" msgstr "" #: scene/3d/path.cpp -#, fuzzy msgid "PathFollow only works when set as a child of a Path node." -msgstr "" -"PathFollow2D ã¯ã€Path2D ノードã®åã¨ã—ã¦è¨å®šã•れã¦ã„ã‚‹å ´åˆã®ã¿å‹•作ã—ã¾ã™ã€‚" +msgstr "PathFollow ã¯ã€Path ノードã®åã¨ã—ã¦è¨å®šã•れã¦ã„ã‚‹å ´åˆã®ã¿å‹•作ã—ã¾ã™ã€‚" #: scene/3d/path.cpp msgid "" @@ -9900,27 +9895,6 @@ msgstr "" "Path プãƒãƒ‘ティã¯ã€å‹•作ã™ã‚‹ã‚ˆã†ã«æœ‰åŠ¹ãª Particles2D ノードを示ã™å¿…è¦ãŒã‚りã¾" "ã™ã€‚" -#: scene/3d/scenario_fx.cpp -msgid "WorldEnvironment needs an Environment resource." -msgstr "" - -#: scene/3d/scenario_fx.cpp -#, fuzzy -msgid "" -"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." -msgstr "" -"WorldEnvironment ã¯ã€ã‚·ãƒ¼ãƒ³ (ã¾ãŸã¯ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹åŒ–ã•れãŸã‚·ãƒ¼ãƒ³ã®ã‚»ãƒƒãƒˆ) ã”ã¨ã«" -"1ã¤ã ã‘許å¯ã•れã¾ã™ã€‚" - -#: scene/3d/scenario_fx.cpp -#, fuzzy -msgid "" -"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " -"this environment's Background Mode to Canvas (for 2D scenes)." -msgstr "" -"ã“ã®WorldEnvironmentã¯ç„¡è¦–ã•れã¾ã—ãŸã€‚ã‚«ãƒ¡ãƒ©ã‚’è¿½åŠ ã™ã‚‹ã‹(3Dシーンã®å ´åˆ)ã€ã“" -"ã®Environmentã® Backgroundモード ã‚’ Canvas ã«è¨å®šã—ã¾ã™(2Dシーンã®å ´åˆ)。" - #: scene/3d/soft_body.cpp msgid "This body will be ignored until you set a mesh" msgstr "" @@ -9946,6 +9920,27 @@ msgid "" "it as a child of a VehicleBody." msgstr "" +#: scene/3d/world_environment.cpp +msgid "WorldEnvironment needs an Environment resource." +msgstr "" + +#: scene/3d/world_environment.cpp +#, fuzzy +msgid "" +"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." +msgstr "" +"WorldEnvironment ã¯ã€ã‚·ãƒ¼ãƒ³ (ã¾ãŸã¯ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹åŒ–ã•れãŸã‚·ãƒ¼ãƒ³ã®ã‚»ãƒƒãƒˆ) ã”ã¨ã«" +"1ã¤ã ã‘許å¯ã•れã¾ã™ã€‚" + +#: scene/3d/world_environment.cpp +#, fuzzy +msgid "" +"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " +"this environment's Background Mode to Canvas (for 2D scenes)." +msgstr "" +"ã“ã®WorldEnvironmentã¯ç„¡è¦–ã•れã¾ã—ãŸã€‚ã‚«ãƒ¡ãƒ©ã‚’è¿½åŠ ã™ã‚‹ã‹(3Dシーンã®å ´åˆ)ã€ã“" +"ã®Environmentã® Backgroundモード ã‚’ Canvas ã«è¨å®šã—ã¾ã™(2Dシーンã®å ´åˆ)。" + #: scene/animation/animation_blend_tree.cpp msgid "On BlendTree node '%s', animation not found: '%s'" msgstr "" @@ -9972,9 +9967,9 @@ msgid "A root AnimationNode for the graph is not set." msgstr "" #: scene/animation/animation_tree.cpp -#, fuzzy msgid "Path to an AnimationPlayer node containing animations is not set." -msgstr "シーンツリーã‹ã‚‰ã‚¢ãƒ‹ãƒ¡ãƒ¼ã‚·ãƒ§ãƒ³ãƒ—ãƒ¬ã‚¤ãƒ¤ãƒ¼ã‚’é¸æŠžã—アニメーション編集" +msgstr "" +"アニメーションをå«ã‚“ã AnimationPlayer ノードã¸ã®ãƒ‘スãŒè¨å®šã•れã¦ã„ã¾ã›ã‚“。" #: scene/animation/animation_tree.cpp msgid "Path set for AnimationPlayer does not lead to an AnimationPlayer node." @@ -9991,12 +9986,21 @@ msgstr "" "ã“ã®ãƒŽãƒ¼ãƒ‰ã¯éžæŽ¨å¥¨ã«ãªã‚Šã¾ã—ãŸã€‚代ã‚りã«AnimationTreeを使用ã—ã¦ãã ã•ã„。" #: scene/gui/color_picker.cpp +msgid "Pick a color from the screen." +msgstr "" + +#: scene/gui/color_picker.cpp #, fuzzy msgid "Raw Mode" msgstr "パン・モード" #: scene/gui/color_picker.cpp -msgid "Add current color as a preset" +msgid "Switch between hexadecimal and code values." +msgstr "" + +#: scene/gui/color_picker.cpp +#, fuzzy +msgid "Add current color as a preset." msgstr "ç¾åœ¨ã®è‰²ã‚’プリセットã¨ã—ã¦è¿½åŠ " #: scene/gui/dialogs.cpp @@ -10092,6 +10096,18 @@ msgstr "" msgid "Varyings can only be assigned in vertex function." msgstr "" +#~ msgid "Warnings:" +#~ msgstr "è¦å‘Š:" + +#~ msgid "Font Size:" +#~ msgstr "フォントサイズ:" + +#~ msgid "Line:" +#~ msgstr "行:" + +#~ msgid "Col:" +#~ msgstr "列:" + #, fuzzy #~ msgid "OrientedPathFollow only works when set as a child of a Path node." #~ msgstr "" diff --git a/editor/translations/ka.po b/editor/translations/ka.po index d14fe2be04..37f7f2f2e9 100644 --- a/editor/translations/ka.po +++ b/editor/translations/ka.po @@ -4,12 +4,13 @@ # This file is distributed under the same license as the Godot source code. # Giorgi Beriashvili <giorgi.beriashvili@outlook.com>, 2018. # George Dzavashvili <dzavashviligeorge@gmail.com>, 2018. +# დემეტრე შáƒáƒœáƒ˜áƒ <blender.animation.maker@gmail.com>, 2019. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2018-12-13 14:41+0100\n" -"Last-Translator: George Dzavashvili <dzavashviligeorge@gmail.com>\n" +"PO-Revision-Date: 2019-02-10 12:01+0000\n" +"Last-Translator: დემეტრე შáƒáƒœáƒ˜áƒ <blender.animation.maker@gmail.com>\n" "Language-Team: Georgian <https://hosted.weblate.org/projects/godot-engine/" "godot/ka/>\n" "Language: ka\n" @@ -17,7 +18,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Poedit 2.2\n" +"X-Generator: Weblate 3.5-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -69,7 +70,7 @@ msgstr "" #: editor/animation_bezier_editor.cpp msgid "Mirror" -msgstr "" +msgstr "სáƒáƒ კე" #: editor/animation_bezier_editor.cpp #, fuzzy @@ -79,7 +80,7 @@ msgstr "áƒáƒœáƒ˜áƒ› გáƒáƒ¡áƒáƒ¦áƒ”ბის ჩáƒáƒ§áƒ”ნებáƒ" #: editor/animation_bezier_editor.cpp #, fuzzy msgid "Duplicate Selected Key(s)" -msgstr "მáƒáƒœáƒ˜áƒ¨áƒ•ნის áƒáƒ¡áƒšáƒ˜áƒ¡ შექმნáƒ" +msgstr "მáƒáƒœáƒ˜áƒ¨áƒœáƒ£áƒšáƒ˜ გáƒáƒ¡áƒáƒ¦áƒ”ბ(ებ)ის áƒáƒ¡áƒšáƒ˜áƒ¡ შექმნáƒ" #: editor/animation_bezier_editor.cpp #, fuzzy @@ -100,7 +101,7 @@ msgstr "áƒáƒœáƒ˜áƒ›áƒáƒªáƒ˜áƒ˜áƒ¡ გáƒáƒ¡áƒáƒ¦áƒ”ბური კáƒáƒ“რá #: editor/animation_track_editor.cpp msgid "Anim Change Transition" -msgstr "áƒáƒœáƒ˜áƒ›áƒáƒªáƒ˜áƒ˜áƒ¡ გáƒáƒ დáƒáƒ›áƒáƒ›áƒ•ლáƒáƒ‘ის ცვლილებáƒ" +msgstr "áƒáƒœáƒ˜áƒ›áƒáƒªáƒ˜áƒ˜áƒ¡ გáƒáƒ დáƒáƒ›áƒáƒ›áƒ•ლáƒáƒ‘ის შეცვლáƒ" #: editor/animation_track_editor.cpp msgid "Anim Change Transform" @@ -115,16 +116,19 @@ msgid "Anim Change Call" msgstr "áƒáƒœáƒ˜áƒ›áƒáƒªáƒ˜áƒ˜áƒ¡ ძáƒáƒ®áƒ˜áƒšáƒ˜áƒ¡ ცვლილებáƒ" #: editor/animation_track_editor.cpp +#, fuzzy msgid "Property Track" -msgstr "" +msgstr "áƒáƒ‘იექტზე დáƒáƒ™áƒ•ირვებáƒ" #: editor/animation_track_editor.cpp +#, fuzzy msgid "3D Transform Track" -msgstr "" +msgstr "3D გáƒáƒ დáƒáƒ¥áƒ›áƒœáƒ˜áƒ¡ დáƒáƒ™áƒ•ირვებáƒ" #: editor/animation_track_editor.cpp +#, fuzzy msgid "Call Method Track" -msgstr "" +msgstr "მეთáƒáƒ“ის გáƒáƒ›áƒáƒ«áƒáƒ®áƒ”ბის დáƒáƒ™áƒ•ირვებáƒ" #: editor/animation_track_editor.cpp msgid "Bezier Curve Track" @@ -139,7 +143,6 @@ msgid "Animation Playback Track" msgstr "" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Add Track" msgstr "áƒáƒœáƒ˜áƒ›áƒáƒªáƒ˜áƒ˜áƒ¡ თრექის დáƒáƒ›áƒáƒ¢áƒ”ბáƒ" @@ -151,32 +154,35 @@ msgstr "áƒáƒœáƒ˜áƒ›áƒáƒªáƒ˜áƒ˜áƒ¡ ხáƒáƒœáƒ’რძლივáƒáƒ‘რ(წრ#: editor/animation_track_editor.cpp #, fuzzy msgid "Animation Looping" -msgstr "áƒáƒœáƒ˜áƒ›áƒáƒªáƒ˜áƒ˜áƒ¡ ზუმი." +msgstr "áƒáƒœáƒ˜áƒ›áƒáƒªáƒ˜áƒ˜áƒ¡ ბრუნვáƒ" #: editor/animation_track_editor.cpp #: modules/visual_script/visual_script_editor.cpp msgid "Functions:" -msgstr "" +msgstr "ფუნქციები:" #: editor/animation_track_editor.cpp msgid "Audio Clips:" -msgstr "" +msgstr "ხმáƒáƒ•áƒáƒœáƒ˜ მáƒáƒœáƒáƒ™áƒ•ეთები:" #: editor/animation_track_editor.cpp msgid "Anim Clips:" -msgstr "" +msgstr "áƒáƒœáƒ˜áƒ›áƒáƒªáƒ˜áƒ˜áƒ¡ მáƒáƒœáƒáƒ™áƒ•ეთები:" #: editor/animation_track_editor.cpp +#, fuzzy msgid "Toggle this track on/off." -msgstr "" +msgstr "ჩáƒáƒœáƒáƒ¬áƒ”რის ჩáƒáƒ თვრ/ გáƒáƒ›áƒáƒ თვáƒ" #: editor/animation_track_editor.cpp +#, fuzzy msgid "Update Mode (How this property is set)" -msgstr "" +msgstr "გáƒáƒœáƒáƒ®áƒšáƒ”ბის რეჟიმი (რáƒáƒ’áƒáƒ áƒáƒª ეს პáƒáƒ áƒáƒ›áƒ”ტრირდáƒáƒ§áƒ”ნებული)" #: editor/animation_track_editor.cpp +#, fuzzy msgid "Interpolation Mode" -msgstr "" +msgstr "ინტერპáƒáƒšáƒáƒªáƒ˜áƒ˜áƒ¡ რეჟიმი" #: editor/animation_track_editor.cpp msgid "Loop Wrap Mode (Interpolate end with beginning on loop)" @@ -185,12 +191,12 @@ msgstr "" #: editor/animation_track_editor.cpp #, fuzzy msgid "Remove this track." -msgstr "მáƒáƒœáƒ˜áƒ¨áƒœáƒ£áƒšáƒ˜ თრექის წáƒáƒ¨áƒšáƒ." +msgstr "მáƒáƒœáƒ˜áƒ¨áƒœáƒ£áƒšáƒ˜ ჩáƒáƒœáƒáƒ¬áƒ”რის წáƒáƒ¨áƒšáƒ." #: editor/animation_track_editor.cpp #, fuzzy msgid "Time (s): " -msgstr "ნáƒáƒ‘იჯი (წáƒáƒ›áƒ˜):" +msgstr "დრრ(წáƒáƒ›áƒ˜): " #: editor/animation_track_editor.cpp msgid "Continuous" @@ -206,11 +212,11 @@ msgstr "სáƒáƒ¡áƒ®áƒšáƒ”ტი" #: editor/animation_track_editor.cpp msgid "Capture" -msgstr "" +msgstr "გáƒáƒ“áƒáƒ¦áƒ”ბáƒ" #: editor/animation_track_editor.cpp msgid "Nearest" -msgstr "" +msgstr "უáƒáƒ®áƒšáƒáƒ”სი" #: editor/animation_track_editor.cpp editor/plugins/curve_editor_plugin.cpp #: editor/property_editor.cpp @@ -219,7 +225,7 @@ msgstr "წრფივი" #: editor/animation_track_editor.cpp msgid "Cubic" -msgstr "" +msgstr "კუბური" #: editor/animation_track_editor.cpp msgid "Clamp Loop Interp" @@ -232,7 +238,7 @@ msgstr "" #: editor/animation_track_editor.cpp #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Insert Key" -msgstr "" +msgstr "ჩáƒáƒ¡áƒ•ით გáƒáƒ¡áƒáƒ¦áƒ”ბი" #: editor/animation_track_editor.cpp #, fuzzy @@ -249,12 +255,13 @@ msgid "Remove Anim Track" msgstr "áƒáƒœáƒ˜áƒ›áƒáƒªáƒ˜áƒ˜áƒ¡ თრექის წáƒáƒ¨áƒšáƒ" #: editor/animation_track_editor.cpp +#, fuzzy msgid "Create NEW track for %s and insert key?" -msgstr "áƒáƒ®áƒáƒšáƒ˜ თრექის შექმნრ%s სთვის დრგáƒáƒ¡áƒáƒ¦áƒ”ბის ჩáƒáƒ¡áƒ›áƒ?" +msgstr "შევქმნრáƒáƒ®áƒáƒšáƒ˜ მáƒáƒœáƒáƒ™áƒ•ეთი %s-თვის დრჩáƒáƒ•სვრგáƒáƒ¡áƒáƒ¦áƒ”ბი?" #: editor/animation_track_editor.cpp msgid "Create %d NEW tracks and insert keys?" -msgstr "áƒáƒ®áƒáƒšáƒ˜ %d თრექების შექმნრდრგáƒáƒ¡áƒáƒ¦áƒ”ბების ჩáƒáƒ¡áƒ›áƒ?" +msgstr "áƒáƒ®áƒáƒšáƒ˜ %d ჩáƒáƒœáƒáƒ¬áƒ”რების შექმნრდრგáƒáƒ¡áƒáƒ¦áƒ”ბების ჩáƒáƒ¡áƒ›áƒ?" #: editor/animation_track_editor.cpp editor/create_dialog.cpp #: editor/editor_audio_buses.cpp editor/editor_plugin_settings.cpp @@ -270,8 +277,11 @@ msgid "Anim Insert" msgstr "áƒáƒœáƒ˜áƒ› ჩáƒáƒ§áƒ”ნებáƒ" #: editor/animation_track_editor.cpp +#, fuzzy msgid "AnimationPlayer can't animate itself, only other players." msgstr "" +"áƒáƒœáƒ˜áƒ›áƒáƒªáƒ˜áƒ˜áƒ¡ გáƒáƒ›áƒ¨áƒ•ები ვერჩáƒáƒáƒ¢áƒáƒ ებს ცდებს სáƒáƒ™áƒ£áƒ—áƒáƒ თáƒáƒ•ზე, მხáƒáƒšáƒáƒ“ სხვრ" +"მáƒáƒ—áƒáƒ›áƒáƒ¨áƒ”ებზე." #: editor/animation_track_editor.cpp msgid "Anim Create & Insert" @@ -279,7 +289,7 @@ msgstr "áƒáƒœáƒ˜áƒ› შექმნრ& ჩáƒáƒ§áƒ”ნებáƒ" #: editor/animation_track_editor.cpp msgid "Anim Insert Track & Key" -msgstr "áƒáƒœáƒ˜áƒ›áƒáƒªáƒ˜áƒ˜áƒ¡ თრექის დრგáƒáƒ¡áƒáƒ¦áƒ”ბის ჩáƒáƒ›áƒáƒ¢áƒ”ბáƒ" +msgstr "áƒáƒœáƒ˜áƒ›áƒáƒªáƒ˜áƒ˜áƒ¡ ჩáƒáƒœáƒáƒ¬áƒ”რის დრგáƒáƒ¡áƒáƒ¦áƒ”ბის ჩáƒáƒ›áƒáƒ¢áƒ”ბáƒ" #: editor/animation_track_editor.cpp msgid "Anim Insert Key" @@ -307,35 +317,39 @@ msgstr "" #: editor/animation_track_editor.cpp msgid "Not possible to add a new track without a root" -msgstr "" +msgstr "შეუძლებელირდáƒáƒáƒ›áƒáƒ¢áƒ áƒáƒ®áƒáƒšáƒ˜ ჩáƒáƒœáƒáƒ¬áƒ”რი ფესვის გáƒáƒ ეშე" #: editor/animation_track_editor.cpp +#, fuzzy msgid "Track path is invalid, so can't add a key." -msgstr "" +msgstr "ჩáƒáƒœáƒáƒ¬áƒ”რის მისáƒáƒ›áƒáƒ თი áƒáƒ áƒáƒ¡áƒ¬áƒáƒ იáƒ, áƒáƒ¡áƒ” რáƒáƒ› შეუძლებელირგáƒáƒ¡áƒáƒ¦áƒ”ბის დáƒáƒ›áƒáƒ¢áƒ”ბáƒ" #: editor/animation_track_editor.cpp msgid "Track is not of type Spatial, can't insert key" -msgstr "" +msgstr "ჩáƒáƒœáƒáƒ¬áƒ”რი áƒáƒ áƒáƒ ის სივრცის სáƒáƒ®áƒ˜áƒ¡, ვერჩáƒáƒ¡áƒ•áƒáƒ›áƒ— გáƒáƒ¡áƒáƒ¦áƒ”ბს" #: editor/animation_track_editor.cpp msgid "Track path is invalid, so can't add a method key." msgstr "" +"ჩáƒáƒœáƒáƒ¬áƒ”რის მისáƒáƒ›áƒáƒ თი áƒáƒ áƒáƒ¡áƒ¬áƒáƒ იáƒ, áƒáƒ¡áƒ” რáƒáƒ› შეუძლებელირმეთáƒáƒ“ური გáƒáƒ¡áƒáƒ¦áƒ”ბის " +"დáƒáƒ›áƒáƒ¢áƒ”ბáƒ." #: editor/animation_track_editor.cpp msgid "Method not found in object: " -msgstr "" +msgstr "მეთáƒáƒ“ი ვერმáƒáƒ˜áƒ«áƒ”ბნრáƒáƒ‘იექტში: " #: editor/animation_track_editor.cpp msgid "Anim Move Keys" msgstr "áƒáƒœáƒ˜áƒ›áƒáƒªáƒ˜áƒ˜áƒ¡ გáƒáƒ¡áƒáƒ¦áƒ”ბების გáƒáƒ“áƒáƒáƒ“გილებáƒ" #: editor/animation_track_editor.cpp +#, fuzzy msgid "Clipboard is empty" -msgstr "" +msgstr "ბუფერი ცáƒáƒ იელიáƒ" #: editor/animation_track_editor.cpp msgid "Anim Scale Keys" -msgstr "áƒáƒœáƒ˜áƒ› გáƒáƒ¡áƒáƒ¦áƒ”ბების შკáƒáƒšáƒ˜áƒ ებáƒ" +msgstr "áƒáƒœáƒ˜áƒ› გáƒáƒ¡áƒáƒ¦áƒ”ბების ზáƒáƒ›áƒ˜áƒ¡ შეცვლáƒ" #: editor/animation_track_editor.cpp msgid "" @@ -344,21 +358,19 @@ msgstr "" #: editor/animation_track_editor.cpp msgid "Only show tracks from nodes selected in tree." -msgstr "" +msgstr "მხáƒáƒšáƒáƒ“ áƒáƒ©áƒ•ენე ჩáƒáƒœáƒáƒ¬áƒ”რები კვáƒáƒœáƒ«áƒ”ბიდáƒáƒœ მáƒáƒœáƒ˜áƒ¨áƒœáƒ£áƒšáƒ˜ ხეში." #: editor/animation_track_editor.cpp msgid "Group tracks by node or display them as plain list." -msgstr "" +msgstr "დáƒáƒáƒ¯áƒ’უფე ჩáƒáƒœáƒáƒ¬áƒ”რები კვáƒáƒœáƒ«áƒ”ბის მიხედვით áƒáƒœ áƒáƒ©áƒ•ენე რáƒáƒ’áƒáƒ ც უბრáƒáƒšáƒ სიáƒ." #: editor/animation_track_editor.cpp -#, fuzzy msgid "Snap (s): " -msgstr "ნáƒáƒ‘იჯი (წáƒáƒ›áƒ˜):" +msgstr "ნáƒáƒ‘იჯი (s): " #: editor/animation_track_editor.cpp -#, fuzzy msgid "Animation step value." -msgstr "áƒáƒœáƒ˜áƒ›áƒáƒªáƒ˜áƒ˜áƒ¡ ზუმი." +msgstr "áƒáƒœáƒ˜áƒ›áƒáƒªáƒ˜áƒ˜áƒ¡ ნáƒáƒ‘იჯის ღირებულებáƒ." #: editor/animation_track_editor.cpp editor/editor_properties.cpp #: editor/plugins/polygon_2d_editor_plugin.cpp @@ -367,12 +379,11 @@ msgstr "áƒáƒœáƒ˜áƒ›áƒáƒªáƒ˜áƒ˜áƒ¡ ზუმი." #: editor/project_manager.cpp editor/project_settings_editor.cpp #: editor/property_editor.cpp modules/visual_script/visual_script_editor.cpp msgid "Edit" -msgstr "" +msgstr "შეცვლáƒ" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Animation properties." -msgstr "áƒáƒœáƒ˜áƒ›áƒáƒªáƒ˜áƒ˜áƒ¡ ზუმი." +msgstr "áƒáƒœáƒ˜áƒ›áƒáƒªáƒ˜áƒ˜áƒ¡ . პáƒáƒ áƒáƒ›áƒ”ტრები." #: editor/animation_track_editor.cpp msgid "Copy Tracks" @@ -549,22 +560,14 @@ msgstr "ზუმის დáƒáƒžáƒáƒ¢áƒáƒ áƒáƒ•ებáƒ" msgid "Reset Zoom" msgstr "ზუმის სáƒáƒ¬áƒ§áƒ˜áƒ¡áƒ–ე დáƒáƒ§áƒ”ნებáƒ" -#: editor/code_editor.cpp -msgid "Warnings:" +#: editor/code_editor.cpp modules/mono/editor/mono_bottom_panel.cpp +msgid "Warnings" msgstr "" #: editor/code_editor.cpp -msgid "Font Size:" +msgid "Line and column numbers." msgstr "" -#: editor/code_editor.cpp -msgid "Line:" -msgstr "ხáƒáƒ–ი:" - -#: editor/code_editor.cpp -msgid "Col:" -msgstr "სვეტი:" - #: editor/connections_dialog.cpp msgid "Method in target Node must be specified!" msgstr "სáƒáƒ›áƒ˜áƒ–ნე კვáƒáƒœáƒ«áƒ¨áƒ˜ მეთáƒáƒ“ი უნდრიყáƒáƒ¡ გáƒáƒœáƒ¡áƒáƒ–ღვრული!" @@ -869,8 +872,8 @@ msgstr "წáƒáƒ•შáƒáƒšáƒáƒ— მáƒáƒœáƒ˜áƒ¨áƒœáƒ£áƒšáƒ˜ ფáƒáƒ˜áƒšáƒ”ბá #: editor/dependency_editor.cpp editor/editor_audio_buses.cpp #: editor/editor_file_dialog.cpp editor/editor_node.cpp #: editor/filesystem_dock.cpp editor/plugins/item_list_editor_plugin.cpp -#: editor/project_export.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_dock.cpp +#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp +#: editor/project_settings_editor.cpp editor/scene_tree_dock.cpp msgid "Delete" msgstr "წáƒáƒ¨áƒšáƒ" @@ -1127,7 +1130,7 @@ msgid "Add Bus" msgstr "" #: editor/editor_audio_buses.cpp -msgid "Create a new Bus Layout." +msgid "Add a new Audio Bus to this layout." msgstr "" #: editor/editor_audio_buses.cpp editor/editor_properties.cpp @@ -1156,6 +1159,10 @@ msgstr "" msgid "Load the default Bus Layout." msgstr "" +#: editor/editor_audio_buses.cpp +msgid "Create a new Bus Layout." +msgstr "" + #: editor/editor_autoload_settings.cpp msgid "Invalid name." msgstr "" @@ -2339,7 +2346,7 @@ msgid "Save & Restart" msgstr "" #: editor/editor_node.cpp -msgid "Spins when the editor window repaints!" +msgid "Spins when the editor window redraws." msgstr "" #: editor/editor_node.cpp @@ -3389,39 +3396,39 @@ msgid "Create Polygon" msgstr "შექმნáƒ" #: editor/plugins/abstract_polygon_2d_editor.cpp +#: editor/plugins/animation_blend_space_1d_editor.cpp +#: editor/plugins/animation_blend_space_2d_editor.cpp #, fuzzy -msgid "Edit Polygon" +msgid "Create points." msgstr "შექმნáƒ" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Insert Point" -msgstr "" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Edit Polygon (Remove Point)" +msgid "" +"Edit points.\n" +"LMB: Move Point\n" +"RMB: Erase Point" msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Remove Polygon And Point" +#: editor/plugins/animation_blend_space_1d_editor.cpp +msgid "Erase points." msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -#: editor/plugins/animation_blend_space_1d_editor.cpp -#: editor/plugins/animation_blend_space_2d_editor.cpp #, fuzzy -msgid "Create points." +msgid "Edit Polygon" msgstr "შექმნáƒ" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "" -"Edit points.\n" -"LMB: Move Point\n" -"RMB: Erase Point" +msgid "Insert Point" msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -#: editor/plugins/animation_blend_space_1d_editor.cpp -msgid "Erase points." +msgid "Edit Polygon (Remove Point)" +msgstr "" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Remove Polygon And Point" msgstr "" #: editor/plugins/animation_blend_space_1d_editor.cpp @@ -4211,6 +4218,16 @@ msgid "Move CanvasItem" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp +msgid "Presets for the anchors and margins values of a Control node." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp +msgid "" +"Children of containers have their anchors and margins values overridden by " +"their parent." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp msgid "Anchors only" msgstr "" @@ -5112,6 +5129,12 @@ msgid "Create UV Map" msgstr "" #: editor/plugins/polygon_2d_editor_plugin.cpp +msgid "" +"Polygon 2D has internal vertices, so it can no longer be edited in the " +"viewport." +msgstr "" + +#: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Create Polygon & UV" msgstr "" @@ -6211,7 +6234,7 @@ msgid "Post" msgstr "" #: editor/plugins/spatial_editor_plugin.cpp -msgid "Name-less gizmo" +msgid "Nameless gizmo" msgstr "" #: editor/plugins/sprite_editor_plugin.cpp @@ -6288,8 +6311,14 @@ msgid "(empty)" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animations" -msgstr "" +#, fuzzy +msgid "Animations:" +msgstr "ფუნქციები:" + +#: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "New Animation" +msgstr "áƒáƒœáƒ˜áƒ›áƒáƒªáƒ˜áƒ˜áƒ¡ áƒáƒžáƒ¢áƒ˜áƒ›áƒ˜áƒ–áƒáƒªáƒ˜áƒ" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed (FPS):" @@ -6300,8 +6329,9 @@ msgid "Loop" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animation Frames" -msgstr "" +#, fuzzy +msgid "Animation Frames:" +msgstr "áƒáƒœáƒ˜áƒ›áƒáƒªáƒ˜áƒ˜áƒ¡ . პáƒáƒ áƒáƒ›áƒ”ტრები." #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Insert Empty (Before)" @@ -7092,6 +7122,19 @@ msgstr "" #: editor/project_manager.cpp msgid "" +"The following project settings file does not specify the version of Godot " +"through which it was created.\n" +"\n" +"%s\n" +"\n" +"If you proceed with opening it, it will be converted to Godot's current " +"configuration file format.\n" +"Warning: You will not be able to open the project with previous versions of " +"the engine anymore." +msgstr "" + +#: editor/project_manager.cpp +msgid "" "The following project settings file was generated by an older engine " "version, and needs to be converted for this version:\n" "\n" @@ -8576,10 +8619,6 @@ msgid "Build Project" msgstr "" #: modules/mono/editor/mono_bottom_panel.cpp -msgid "Warnings" -msgstr "" - -#: modules/mono/editor/mono_bottom_panel.cpp msgid "View log" msgstr "" @@ -9212,6 +9251,13 @@ msgid "" "ParallaxLayer node only works when set as child of a ParallaxBackground node." msgstr "" +#: scene/2d/particles_2d.cpp +msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles2D node instead. You can use the \"Convert to " +"CPUParticles\" option for this purpose." +msgstr "" + #: scene/2d/particles_2d.cpp scene/3d/particles.cpp msgid "" "A material to process the particles is not assigned, so no behavior is " @@ -9367,6 +9413,13 @@ msgstr "" #: scene/3d/particles.cpp msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles node instead. You can use the \"Convert to CPUParticles" +"\" option for this purpose." +msgstr "" + +#: scene/3d/particles.cpp +msgid "" "Nothing is visible because meshes have not been assigned to draw passes." msgstr "" @@ -9397,21 +9450,6 @@ msgstr "" msgid "Path property must point to a valid Spatial node to work." msgstr "" -#: scene/3d/scenario_fx.cpp -msgid "WorldEnvironment needs an Environment resource." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " -"this environment's Background Mode to Canvas (for 2D scenes)." -msgstr "" - #: scene/3d/soft_body.cpp msgid "This body will be ignored until you set a mesh" msgstr "" @@ -9435,6 +9473,21 @@ msgid "" "it as a child of a VehicleBody." msgstr "" +#: scene/3d/world_environment.cpp +msgid "WorldEnvironment needs an Environment resource." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " +"this environment's Background Mode to Canvas (for 2D scenes)." +msgstr "" + #: scene/animation/animation_blend_tree.cpp msgid "On BlendTree node '%s', animation not found: '%s'" msgstr "" @@ -9480,11 +9533,19 @@ msgid "This node has been deprecated. Use AnimationTree instead." msgstr "" #: scene/gui/color_picker.cpp +msgid "Pick a color from the screen." +msgstr "" + +#: scene/gui/color_picker.cpp msgid "Raw Mode" msgstr "" #: scene/gui/color_picker.cpp -msgid "Add current color as a preset" +msgid "Switch between hexadecimal and code values." +msgstr "" + +#: scene/gui/color_picker.cpp +msgid "Add current color as a preset." msgstr "" #: scene/gui/dialogs.cpp @@ -9568,6 +9629,12 @@ msgstr "" msgid "Varyings can only be assigned in vertex function." msgstr "" +#~ msgid "Line:" +#~ msgstr "ხáƒáƒ–ი:" + +#~ msgid "Col:" +#~ msgstr "სვეტი:" + #, fuzzy #~ msgid "Remove Split" #~ msgstr "მáƒáƒœáƒ˜áƒ¨áƒ•ნის მáƒáƒ¨áƒáƒ ებáƒ" diff --git a/editor/translations/ko.po b/editor/translations/ko.po index 23e4633092..ebf31640fc 100644 --- a/editor/translations/ko.po +++ b/editor/translations/ko.po @@ -16,7 +16,7 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2019-01-26 21:22+0000\n" +"PO-Revision-Date: 2019-02-18 08:54+0000\n" "Last-Translator: ì†¡íƒœì„ <xotjq237@gmail.com>\n" "Language-Team: Korean <https://hosted.weblate.org/projects/godot-engine/" "godot/ko/>\n" @@ -49,23 +49,23 @@ msgstr "ì¸ìŠ¤í„´ìŠ¤ê°€ 비어있기 ë•Œë¬¸ì— Self를 ì‚¬ìš©í• ìˆ˜ ì—†ìŠµë‹ˆë‹ #: core/math/expression.cpp msgid "Invalid operands to operator %s, %s and %s." -msgstr "ì—°ì‚°ìž %s, %s ë° %s ì˜ ì—°ì‚° 대ìƒì´ ìœ íš¨í•˜ì§€ 않습니다." +msgstr "ì—°ì‚°ìž %s, %s ê·¸ë¦¬ê³ %sì˜ ì—°ì‚° 대ìƒì´ ìœ íš¨í•˜ì§€ 않습니다." #: core/math/expression.cpp msgid "Invalid index of type %s for base type %s" -msgstr "ë² ì´ìФ 타입 %s ì— ìœ íš¨í•˜ì§€ ì•Šì€ ì¸ë±ìФ 타입 %s" +msgstr "ë² ì´ìФ 타입 %sì— ìœ íš¨í•˜ì§€ ì•Šì€ ì¸ë±ìФ 타입 %s" #: core/math/expression.cpp msgid "Invalid named index '%s' for base type %s" -msgstr "ë² ì´ìФ 타입 %s ì— ìœ íš¨í•˜ì§€ ì•Šì€ ì¸ë±ìФ ì´ë¦„ %s" +msgstr "ë² ì´ìФ 타입 %sì— ìœ íš¨í•˜ì§€ ì•Šì€ ì¸ë±ìФ ì´ë¦„ %s" #: core/math/expression.cpp msgid "Invalid arguments to construct '%s'" -msgstr "'%s' ì„ êµ¬ì„±í•˜ê¸°ì— ìœ íš¨í•˜ì§€ ì•Šì€ ì¸ìˆ˜" +msgstr "'%s'ì„(를) êµ¬ì„±í•˜ê¸°ì— ìœ íš¨í•˜ì§€ ì•Šì€ ì¸ìˆ˜" #: core/math/expression.cpp msgid "On call to '%s':" -msgstr "'%s' 를 호출 시:" +msgstr "'%s'ì„(를) 호출 시:" #: editor/animation_bezier_editor.cpp #: editor/plugins/asset_library_editor_plugin.cpp @@ -249,7 +249,7 @@ msgstr "ì• ë‹ˆë©”ì´ì…˜ 트랙 ì‚ì œ" #: editor/animation_track_editor.cpp msgid "Create NEW track for %s and insert key?" -msgstr "%s (ì„)를 위해 새 íŠ¸ëž™ì„ ë§Œë“¤ê³ í‚¤ë¥¼ ì‚½ìž…í•˜ì‹œê² ìŠµë‹ˆê¹Œ?" +msgstr "%sì„(를) 위해 새 íŠ¸ëž™ì„ ë§Œë“¤ê³ í‚¤ë¥¼ ì‚½ìž…í•˜ì‹œê² ìŠµë‹ˆê¹Œ?" #: editor/animation_track_editor.cpp msgid "Create %d NEW tracks and insert keys?" @@ -548,21 +548,14 @@ msgstr "축소" msgid "Reset Zoom" msgstr "줌 리셋" -#: editor/code_editor.cpp -msgid "Warnings:" -msgstr "ê²½ê³ :" - -#: editor/code_editor.cpp -msgid "Font Size:" -msgstr "í°íЏ í¬ê¸°:" - -#: editor/code_editor.cpp -msgid "Line:" -msgstr "ë¼ì¸:" +#: editor/code_editor.cpp modules/mono/editor/mono_bottom_panel.cpp +msgid "Warnings" +msgstr "ê²½ê³ " #: editor/code_editor.cpp -msgid "Col:" -msgstr "칼럼:" +#, fuzzy +msgid "Line and column numbers." +msgstr "ë¼ì¸ ë° ì»¬ëŸ¼ 번호" #: editor/connections_dialog.cpp msgid "Method in target Node must be specified!" @@ -639,11 +632,11 @@ msgstr "ì—°ê²°" #: editor/connections_dialog.cpp msgid "Connect '%s' to '%s'" -msgstr "'%s'를 '%s'ì— ì—°ê²°" +msgstr "'%s'ì„(를) '%s'ì— ì—°ê²°" #: editor/connections_dialog.cpp msgid "Disconnect '%s' from '%s'" -msgstr "'%s'와 '%s'ì˜ ì—°ê²° í•´ì œ" +msgstr "'%s'와(ê³¼) '%s'ì˜ ì—°ê²° í•´ì œ" #: editor/connections_dialog.cpp msgid "Disconnect all from signal: '%s'" @@ -672,7 +665,7 @@ msgstr "\"%s\" 시그ë„ì—서 ëª¨ë“ ì—°ê²°ì„ ì‚ì œí•˜ì‹œê² ìŠµë‹ˆê¹Œ?" #: editor/connections_dialog.cpp editor/editor_help.cpp editor/node_dock.cpp msgid "Signals" -msgstr "시그ë„(Signal)" +msgstr "시그ë„" #: editor/connections_dialog.cpp msgid "Are you sure you want to remove all connections from this signal?" @@ -692,7 +685,7 @@ msgstr "메서드로 ì´ë™" #: editor/create_dialog.cpp msgid "Change %s Type" -msgstr "%s로 타입 변경" +msgstr "%s(으)로 타입 변경" #: editor/create_dialog.cpp editor/project_settings_editor.cpp #: modules/visual_script/visual_script_editor.cpp @@ -744,7 +737,7 @@ msgid "" "Scene '%s' is currently being edited.\n" "Changes will not take effect unless reloaded." msgstr "" -"씬 '%s'(ì´)ê°€ 현재 편집 중입니다.\n" +"씬 '%s'ì´(ê°€) 현재 편집 중입니다.\n" "다시 불러올 때 변경 사í•ì´ ì ìš©ë©ë‹ˆë‹¤." #: editor/dependency_editor.cpp @@ -818,7 +811,7 @@ msgstr "ì‚ì œí• ìˆ˜ 없습니다:" #: editor/dependency_editor.cpp msgid "Error loading:" -msgstr "불러오기 중 ì—러:" +msgstr "불러오기 중 오류:" #: editor/dependency_editor.cpp msgid "Load failed due to missing dependencies:" @@ -838,7 +831,7 @@ msgstr "ì¢…ì† ê´€ê³„ ìˆ˜ì •" #: editor/dependency_editor.cpp msgid "Errors loading!" -msgstr "불러오기 중 ì—러 ë°œìƒ!" +msgstr "불러오기 중 오류 ë°œìƒ!" #: editor/dependency_editor.cpp msgid "Permanently delete %d item(s)? (No undo!)" @@ -863,8 +856,8 @@ msgstr "ì„ íƒëœ 파ì¼ë“¤ì„ ì‚ì œí•˜ì‹œê² ìŠµë‹ˆê¹Œ?" #: editor/dependency_editor.cpp editor/editor_audio_buses.cpp #: editor/editor_file_dialog.cpp editor/editor_node.cpp #: editor/filesystem_dock.cpp editor/plugins/item_list_editor_plugin.cpp -#: editor/project_export.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_dock.cpp +#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp +#: editor/project_settings_editor.cpp editor/scene_tree_dock.cpp msgid "Delete" msgstr "ì‚ì œ" @@ -1119,8 +1112,9 @@ msgid "Add Bus" msgstr "버스 추가" #: editor/editor_audio_buses.cpp -msgid "Create a new Bus Layout." -msgstr "새로운 버스 ë ˆì´ì•„ì›ƒì„ ë§Œë“니다." +#, fuzzy +msgid "Add a new Audio Bus to this layout." +msgstr "오디오 버스 ë ˆì´ì•„ì›ƒì„ ë‹¤ë¥¸ ì´ë¦„으로 ì €ìž¥..." #: editor/editor_audio_buses.cpp editor/editor_properties.cpp #: editor/plugins/animation_player_editor_plugin.cpp editor/property_editor.cpp @@ -1148,6 +1142,10 @@ msgstr "기본값 불러오기" msgid "Load the default Bus Layout." msgstr "기본 버스 ë ˆì´ì•„ì›ƒì„ ë¶ˆëŸ¬ì˜µë‹ˆë‹¤." +#: editor/editor_audio_buses.cpp +msgid "Create a new Bus Layout." +msgstr "새로운 버스 ë ˆì´ì•„ì›ƒì„ ë§Œë“니다." + #: editor/editor_autoload_settings.cpp msgid "Invalid name." msgstr "ìœ íš¨í•˜ì§€ ì•Šì€ ì´ë¦„." @@ -1641,7 +1639,7 @@ msgstr "프로ì 트 내보내기가 오류 코드 %d 로 실패했습니다." #: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp msgid "Error saving resource!" -msgstr "리소스 ì €ìž¥ 중 ì—러!" +msgstr "리소스 ì €ìž¥ 중 오류!" #: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp #: scene/gui/dialogs.cpp @@ -1662,27 +1660,27 @@ msgstr "ìš”ì²í•œ íŒŒì¼ í˜•ì‹ì„ 알 수 ì—†ìŒ:" #: editor/editor_node.cpp msgid "Error while saving." -msgstr "ì €ìž¥ 중 ì—러." +msgstr "ì €ìž¥ 중 오류." #: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp msgid "Can't open '%s'. The file could have been moved or deleted." -msgstr "'%s' 를 ì—´ 수 없습니다. 파ì¼ì´ 존재하지 않습니다." +msgstr "'%s'ì„(를) ì—´ 수 없습니다. 파ì¼ì´ 존재하지 않습니다." #: editor/editor_node.cpp msgid "Error while parsing '%s'." -msgstr "'%s' 파싱 중 ì—러." +msgstr "'%s' 구문 ë¶„ì„ ì¤‘ 오류." #: editor/editor_node.cpp msgid "Unexpected end of file '%s'." -msgstr "예ìƒì¹˜ 못한 파ì¼ì˜ ë '%s' 입니다..." +msgstr "예ìƒì¹˜ 못한 '%s' 파ì¼ì˜ ë." #: editor/editor_node.cpp msgid "Missing '%s' or its dependencies." -msgstr "'%s' 없거나 ì¢…ì† í•ëª©ì´ ì—†ìŠµë‹ˆë‹¤." +msgstr "'%s'ì´(ê°€) 없거나 ì¢…ì† í•ëª©ì´ ì—†ìŠµë‹ˆë‹¤." #: editor/editor_node.cpp msgid "Error while loading '%s'." -msgstr "'%s' 로딩 중 ì—러." +msgstr "'%s' 로딩 중 오류." #: editor/editor_node.cpp msgid "Saving Scene" @@ -1726,7 +1724,7 @@ msgstr "ë³‘í•©í• ë©”ì‹œ ë¼ì´ë¸ŒëŸ¬ë¦¬ë¥¼ 불러올 수 없습니다!" #: editor/editor_node.cpp msgid "Error saving MeshLibrary!" -msgstr "메시 ë¼ì´ë¸ŒëŸ¬ë¦¬ ì €ìž¥ 중 ì—러!" +msgstr "메시 ë¼ì´ë¸ŒëŸ¬ë¦¬ ì €ìž¥ 중 오류!" #: editor/editor_node.cpp msgid "Can't load TileSet for merging!" @@ -1734,11 +1732,11 @@ msgstr "ë³‘í•©í• íƒ€ì¼ì…‹ì„ 불러올 수 없습니다!" #: editor/editor_node.cpp msgid "Error saving TileSet!" -msgstr "타ì¼ì…‹ ì €ìž¥ 중 ì—러!" +msgstr "타ì¼ì…‹ ì €ìž¥ 중 오류!" #: editor/editor_node.cpp msgid "Error trying to save layout!" -msgstr "ë ˆì´ì•„웃 ì €ìž¥ ì‹œë„ ì¤‘ ì—러!" +msgstr "ë ˆì´ì•„웃 ì €ìž¥ ì‹œë„ ì¤‘ 오류!" #: editor/editor_node.cpp msgid "Default editor layout overridden." @@ -1861,7 +1859,7 @@ msgstr "ì €ìž¥ ë° ë‹«ê¸°" #: editor/editor_node.cpp msgid "Save changes to '%s' before closing?" -msgstr "닫기 ì „ì— '%s' ì— ë³€ê²½ì‚¬í•ì„ ì €ìž¥í•˜ì‹œê² ìŠµë‹ˆê¹Œ?" +msgstr "닫기 ì „ì— '%s'ì— ë³€ê²½ì‚¬í•ì„ ì €ìž¥í•˜ì‹œê² ìŠµë‹ˆê¹Œ?" #: editor/editor_node.cpp msgid "Save Scene As..." @@ -1957,35 +1955,35 @@ msgstr "ë©”ì¸ ì”¬ ì„ íƒ" #: editor/editor_node.cpp msgid "Unable to enable addon plugin at: '%s' parsing of config failed." -msgstr "ì• ë“œì˜¨ 플러그ì¸ì„ í™œì„±í™”í• ìˆ˜ 없습니다: '%s' ì„¤ì • í•´ì„ ì‹¤íŒ¨." +msgstr "ì• ë“œì˜¨ 플러그ì¸ì„ í™œì„±í™”í• ìˆ˜ 없습니다: '%s' 구성 구문 ë¶„ì„ ì‹¤íŒ¨." #: editor/editor_node.cpp msgid "Unable to find script field for addon plugin at: 'res://addons/%s'." -msgstr "ì• ë“œì˜¨ 플러그ì¸ì„ ì°¾ì„ ìˆ˜ 없습니다: 'res://addons/%s'." +msgstr "ë‹¤ìŒ ê²½ë¡œì—서 ì• ë“œì˜¨ 플러그ì¸ì„ ì°¾ì„ ìˆ˜ 없습니다: 'res://addons/%s'." #: editor/editor_node.cpp msgid "Unable to load addon script from path: '%s'." -msgstr "ì• ë“œì˜¨ 스í¬ë¦½íŠ¸ë¥¼ 불러올 수 없습니다: '%s'." +msgstr "ë‹¤ìŒ ê²½ë¡œì—서 ì• ë“œì˜¨ 스í¬ë¦½íŠ¸ë¥¼ 불러올 수 없습니다: '%s'." #: editor/editor_node.cpp msgid "" "Unable to load addon script from path: '%s' There seems to be an error in " "the code, please check the syntax." msgstr "" -"해당 경로ì—서 ì• ë“œì˜¨ 스í¬ë¦½íŠ¸ë¥¼ 불러올 수 없습니다: '%s' ì½”ë“œì— ì˜¤ë¥˜ê°€ 있는 " +"ë‹¤ìŒ ê²½ë¡œì—서 ì• ë“œì˜¨ 스í¬ë¦½íŠ¸ë¥¼ 불러올 수 없습니다: '%s' ì½”ë“œì— ì˜¤ë¥˜ê°€ 있는 " "것 같습니다, êµ¬ë¬¸ì„ í™•ì¸í•´ ë³´ì‹ì‹œì˜¤." #: editor/editor_node.cpp msgid "" "Unable to load addon script from path: '%s' Base type is not EditorPlugin." msgstr "" -"해당 경로ì—서 ì• ë“œì˜¨ 스í¬ë¦½íŠ¸ë¥¼ 불러올 수 없습니다: '%s' 기본 íƒ€ìž…ì´ " +"ë‹¤ìŒ ê²½ë¡œì—서 ì• ë“œì˜¨ 스í¬ë¦½íŠ¸ë¥¼ 불러올 수 없습니다: '%s' 기본 íƒ€ìž…ì´ " "EditorPluginì´ ì•„ë‹™ë‹ˆë‹¤." #: editor/editor_node.cpp msgid "Unable to load addon script from path: '%s' Script is not in tool mode." msgstr "" -"해당 경로ì—서 ì• ë“œì˜¨ 스í¬ë¦½íŠ¸ë¥¼ 불러올 수 없습니다: '%s' 스í¬ë¦½íŠ¸ê°€ tool 모드" +"ë‹¤ìŒ ê²½ë¡œì—서 ì• ë“œì˜¨ 스í¬ë¦½íŠ¸ë¥¼ 불러올 수 없습니다: '%s' 스í¬ë¦½íŠ¸ê°€ tool 모드" "ê°€ 아닙니다." #: editor/editor_node.cpp @@ -2001,12 +1999,12 @@ msgid "" "Error loading scene, it must be inside the project path. Use 'Import' to " "open the scene, then save it inside the project path." msgstr "" -"씬 로딩 중 ì—러가 ë°œìƒí–ˆìŠµë‹ˆë‹¤. 프로ì 트 경로 ì•ˆì— ì¡´ìž¬í•´ì•¼ 합니다. 'ê°€ì ¸ì˜¤" +"씬 로딩 중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤. 프로ì 트 경로 ì•ˆì— ì¡´ìž¬í•´ì•¼ 합니다. 'ê°€ì ¸ì˜¤" "기'로 ì”¬ì„ ì—° 후ì—, 프로ì 트 경로 ì•ˆì— ì €ìž¥í•˜ì„¸ìš”." #: editor/editor_node.cpp msgid "Scene '%s' has broken dependencies:" -msgstr "'%s' ì”¬ì˜ ì¢…ì† í•ëª©ì´ ê¹¨ì ¸ìžˆìŠµë‹ˆë‹¤:" +msgstr "'%s' ì”¬ì˜ ì¢…ì† í•ëª©ì´ ê¹¨ì ¸ 있습니다:" #: editor/editor_node.cpp msgid "Clear Recent Scenes" @@ -2383,7 +2381,8 @@ msgid "Save & Restart" msgstr "ì €ìž¥ & 다시 시작" #: editor/editor_node.cpp -msgid "Spins when the editor window repaints!" +#, fuzzy +msgid "Spins when the editor window redraws." msgstr "ì—디터 윈ë„ìš°ê°€ 다시 ê·¸ë ¤ì§ˆ 때 íšŒì „!" #: editor/editor_node.cpp @@ -2457,7 +2456,7 @@ msgstr "새 ìƒì† 씬" #: editor/editor_node.cpp msgid "Load Errors" -msgstr "불러오기 ì—러" +msgstr "불러오기 오류" #: editor/editor_node.cpp editor/plugins/tile_map_editor_plugin.cpp msgid "Select" @@ -2601,7 +2600,7 @@ msgstr "ìœ íš¨í•˜ì§€ ì•Šì€ RID" msgid "" "The selected resource (%s) does not match any type expected for this " "property (%s)." -msgstr "ì„ íƒëœ 리소스(%s)ê°€ ì´ ì†ì„±(%s)ì— ì•Œë§žì€ íƒ€ìž…ì´ ì•„ë‹™ë‹ˆë‹¤." +msgstr "ì„ íƒëœ 리소스 (%s)ê°€ ì´ ì†ì„± (%s)ì— ì•Œë§žì€ íƒ€ìž…ì´ ì•„ë‹™ë‹ˆë‹¤." #: editor/editor_properties.cpp msgid "" @@ -2743,7 +2742,7 @@ msgstr "노드ì—서 ê°€ì ¸ì˜¤ê¸°:" #: editor/export_template_manager.cpp msgid "Re-Download" -msgstr "다시 다운불러오기" +msgstr "다시 다운로드" #: editor/export_template_manager.cpp msgid "Uninstall" @@ -2788,7 +2787,7 @@ msgstr "í…œí”Œë¦¿ì— version.txt를 ì°¾ì„ ìˆ˜ 없습니다." #: editor/export_template_manager.cpp msgid "Error creating path for templates:" -msgstr "템플릿 경로 ìƒì„± ì—러:" +msgstr "템플릿 경로 ìƒì„± 오류:" #: editor/export_template_manager.cpp msgid "Extracting Export Templates" @@ -2850,7 +2849,7 @@ msgstr "" #: editor/export_template_manager.cpp msgid "Error requesting url: " -msgstr "url ìš”ì² ì—러: " +msgstr "url ìš”ì² ì˜¤ë¥˜: " #: editor/export_template_manager.cpp msgid "Connecting to Mirror..." @@ -2892,11 +2891,11 @@ msgstr "다운로드 중" #: editor/export_template_manager.cpp msgid "Connection Error" -msgstr "ì—°ê²° ì—러" +msgstr "ì—°ê²° 오류" #: editor/export_template_manager.cpp msgid "SSL Handshake Error" -msgstr "SSL 핸드ì‰ì´í¬ ì—러" +msgstr "SSL 핸드ì‰ì´í¬ 오류" #: editor/export_template_manager.cpp msgid "Current Version:" @@ -2940,7 +2939,7 @@ msgstr "ì¦ê²¨ì°¾ê¸°" #: editor/filesystem_dock.cpp msgid "Cannot navigate to '%s' as it has not been found in the file system!" -msgstr "íŒŒì¼ ì‹œìŠ¤í…œì—서 '%s'를 ì°¾ì„ ìˆ˜ 없습니다!" +msgstr "íŒŒì¼ ì‹œìŠ¤í…œì—서 '%s'ì„(를) ì°¾ì„ ìˆ˜ 없습니다!" #: editor/filesystem_dock.cpp msgid "View items as a grid of thumbnails." @@ -2965,11 +2964,11 @@ msgstr "í´ë”를 ìžì‹ ì˜ í•˜ìœ„ë¡œ ì´ë™í• 수 없습니다." #: editor/filesystem_dock.cpp msgid "Error moving:" -msgstr "ì´ë™ ì—러:" +msgstr "ì´ë™ 오류:" #: editor/filesystem_dock.cpp msgid "Error duplicating:" -msgstr "ë³µì œ 중 ì—러:" +msgstr "ë³µì œ 중 오류:" #: editor/filesystem_dock.cpp msgid "Unable to update dependencies:" @@ -3173,7 +3172,7 @@ msgstr "그룹 ì´ë¦„ì´ ìž˜ëª»ë˜ì—ˆìŠµë‹ˆë‹¤." #: editor/groups_editor.cpp editor/node_dock.cpp msgid "Groups" -msgstr "그룹(Groups)" +msgstr "그룹" #: editor/groups_editor.cpp msgid "Nodes not in Group" @@ -3209,7 +3208,7 @@ msgstr "ì• ë‹ˆë©”ì´ì…˜ì„ 분리시켜 ê°€ì ¸ì˜¤ê¸°" #: editor/import/resource_importer_scene.cpp msgid "Import with Separate Materials" -msgstr "ë¨¸í„°ë¦¬ì–¼ì„ ë¶„ë¦¬í•´ì„œ ê°€ì ¸ì˜¤ê¸°" +msgstr "ë¨¸í‹°ë¦¬ì–¼ì„ ë¶„ë¦¬í•´ì„œ ê°€ì ¸ì˜¤ê¸°" #: editor/import/resource_importer_scene.cpp msgid "Import with Separate Objects" @@ -3217,7 +3216,7 @@ msgstr "오브ì 트를 분리해서 ê°€ì ¸ì˜¤ê¸°" #: editor/import/resource_importer_scene.cpp msgid "Import with Separate Objects+Materials" -msgstr "오브ì 트와 ë¨¸í„°ë¦¬ì–¼ì„ ë¶„ë¦¬í•´ì„œ ê°€ì ¸ì˜¤ê¸°" +msgstr "오브ì 트와 ë¨¸í‹°ë¦¬ì–¼ì„ ë¶„ë¦¬í•´ì„œ ê°€ì ¸ì˜¤ê¸°" #: editor/import/resource_importer_scene.cpp msgid "Import with Separate Objects+Animations" @@ -3225,11 +3224,11 @@ msgstr "오브ì 트와 ì• ë‹ˆë©”ì´ì…˜ì„ 분리해서 ê°€ì ¸ì˜¤ê¸°" #: editor/import/resource_importer_scene.cpp msgid "Import with Separate Materials+Animations" -msgstr "머터리얼과 ì• ë‹ˆë©”ì´ì…˜ì„ 분리해서 ê°€ì ¸ì˜¤ê¸°" +msgstr "머티리얼과 ì• ë‹ˆë©”ì´ì…˜ì„ 분리해서 ê°€ì ¸ì˜¤ê¸°" #: editor/import/resource_importer_scene.cpp msgid "Import with Separate Objects+Materials+Animations" -msgstr "오브ì 트, 머터리얼, ì• ë‹ˆë©”ì´ì…˜ì„ 분리해서 ê°€ì ¸ì˜¤ê¸°" +msgstr "오브ì 트, 머티리얼, ì• ë‹ˆë©”ì´ì…˜ì„ 분리해서 ê°€ì ¸ì˜¤ê¸°" #: editor/import/resource_importer_scene.cpp msgid "Import as Multiple Scenes" @@ -3237,7 +3236,7 @@ msgstr "ì—¬ëŸ¬ê°œì˜ ì”¬ìœ¼ë¡œ ê°€ì ¸ì˜¤ê¸°" #: editor/import/resource_importer_scene.cpp msgid "Import as Multiple Scenes+Materials" -msgstr "여러 ê°œì˜ ì”¬ê³¼ 머터리얼로 ê°€ì ¸ì˜¤ê¸°" +msgstr "여러 ê°œì˜ ì”¬ê³¼ 머티리얼로 ê°€ì ¸ì˜¤ê¸°" #: editor/import/resource_importer_scene.cpp #: editor/plugins/mesh_library_editor_plugin.cpp @@ -3271,7 +3270,7 @@ msgstr "" #: editor/import/resource_importer_scene.cpp msgid "Error running post-import script:" -msgstr "ê°€ì ¸ì˜¤ê¸° 후 ì‹¤í–‰í• ìŠ¤í¬ë¦½íЏ 실행 중 ì—러:" +msgstr "ê°€ì ¸ì˜¤ê¸° 후 ì‹¤í–‰í• ìŠ¤í¬ë¦½íЏ 실행 중 오류:" #: editor/import/resource_importer_scene.cpp msgid "Saving..." @@ -3279,11 +3278,11 @@ msgstr "ì €ìž¥ 중..." #: editor/import_dock.cpp msgid "Set as Default for '%s'" -msgstr "'%s'를 기본으로 ì§€ì •" +msgstr "'%s'ì„(를) 기본으로 ì§€ì •" #: editor/import_dock.cpp msgid "Clear Default for '%s'" -msgstr "'%s'ì— ëŒ€í•´ 기본값으로 ì§€ì • í•´ì œ" +msgstr "'%s'ì„(를) 기본ì—서 í•´ì œ" #: editor/import_dock.cpp msgid " Files" @@ -3303,17 +3302,18 @@ msgstr "다시 ê°€ì ¸ì˜¤ê¸°" #: editor/import_dock.cpp msgid "Save scenes, re-import and restart" -msgstr "" +msgstr "씬 ì €ìž¥, 다시 ê°€ì ¸ì˜¤ê¸° ë° ë‹¤ì‹œ 시작" #: editor/import_dock.cpp -#, fuzzy msgid "Changing the type of an imported file requires editor restart." -msgstr "비디오 드ë¼ì´ë²„를 ë³€ê²½í•˜ë ¤ë©´ ì—디터를 다시 시작해야 합니다." +msgstr "ê°€ì ¸ì˜¨ 파ì¼ì˜ íƒ€ìž…ì„ ë³€ê²½í•˜ë ¤ë©´ ì—디터를 다시 시작해야 합니다." #: editor/import_dock.cpp msgid "" "WARNING: Assets exist that use this resource, they may stop loading properly." msgstr "" +"ê²½ê³ : ì´ ë¦¬ì†ŒìŠ¤ë¥¼ 사용하는 ì—ì…‹ì´ ì¡´ìž¬í•©ë‹ˆë‹¤, ì—ì…‹ì„ ë¶ˆëŸ¬ì˜¤ì§€ ëª»í• ìˆ˜ 있습니" +"다." #: editor/inspector_dock.cpp msgid "Failed to load resource." @@ -3438,22 +3438,6 @@ msgid "Create Polygon" msgstr "í´ë¦¬ê³¤ 만들기" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Edit Polygon" -msgstr "í´ë¦¬ê³¤ 편집" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Insert Point" -msgstr "í¬ì¸íЏ 삽입" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Edit Polygon (Remove Point)" -msgstr "í´ë¦¬ê³¤ 편집 (í¬ì¸íЏ ì‚ì œ)" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Remove Polygon And Point" -msgstr "í´ë¦¬ê³¤ê³¼ í¬ì¸íЏ ì‚ì œ" - -#: editor/plugins/abstract_polygon_2d_editor.cpp #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp msgid "Create points." @@ -3474,6 +3458,22 @@ msgstr "" msgid "Erase points." msgstr "í¬ì¸íЏ 지우기." +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Edit Polygon" +msgstr "í´ë¦¬ê³¤ 편집" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Insert Point" +msgstr "í¬ì¸íЏ 삽입" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Edit Polygon (Remove Point)" +msgstr "í´ë¦¬ê³¤ 편집 (í¬ì¸íЏ ì‚ì œ)" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Remove Polygon And Point" +msgstr "í´ë¦¬ê³¤ê³¼ í¬ì¸íЏ ì‚ì œ" + #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #: editor/plugins/animation_player_editor_plugin.cpp @@ -3718,7 +3718,7 @@ msgstr "ì• ë‹ˆë©”ì´ì…˜ ë„구" #: editor/plugins/animation_player_editor_plugin.cpp #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Animation" -msgstr "ì• ë‹ˆë©”ì´ì…˜" +msgstr "ì• ë‹ˆë©”ì´ì…˜(Animation)" #: editor/plugins/animation_player_editor_plugin.cpp msgid "New" @@ -3806,7 +3806,7 @@ msgstr "ì• ë‹ˆë©”ì´ì…˜ ì´ë¦„:" #: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp #: editor/script_create_dialog.cpp msgid "Error!" -msgstr "ì—러!" +msgstr "오류!" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Blend Times:" @@ -3822,7 +3822,7 @@ msgstr "êµì°¨-ì• ë‹ˆë©”ì´ì…˜ ë¸”ë Œë“œ 시간" #: editor/plugins/animation_state_machine_editor.cpp msgid "End" -msgstr "ë" +msgstr "End" #: editor/plugins/animation_state_machine_editor.cpp msgid "Immediate" @@ -3846,7 +3846,7 @@ msgstr "하위 ì „í™˜ì— ì‹œìž‘ê³¼ ë 노드가 필요합니다." #: editor/plugins/animation_state_machine_editor.cpp msgid "No playback resource set at path: %s." -msgstr "ê²½ë¡œì— ì„¤ì •ëœ ìž¬ìƒ ë¦¬ì†ŒìŠ¤ ì„¤ì •ì´ ì—†ìŠµë‹ˆë‹¤: %s." +msgstr "ë‹¤ìŒ ê²½ë¡œì— ì„¤ì •ëœ ìž¬ìƒ ë¦¬ì†ŒìŠ¤ê°€ 없습니다: %s." #: editor/plugins/animation_state_machine_editor.cpp msgid "" @@ -4037,7 +4037,7 @@ msgstr "í˜¸ìŠ¤íŠ¸ëª…ì„ ì°¾ì„ ìˆ˜ ì—†ìŒ:" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Connection error, please try again." -msgstr "ì—°ê²° ì—러, 다시 시ë„í•´ 주세요." +msgstr "ì—°ê²° 오류, 다시 시ë„í•´ 주세요." #: editor/plugins/asset_library_editor_plugin.cpp msgid "Can't connect to host:" @@ -4073,7 +4073,7 @@ msgstr "sha256 해시 í™•ì¸ ì‹¤íŒ¨" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Asset Download Error:" -msgstr "ì—ì…‹ 다운로드 ì—러:" +msgstr "ì—ì…‹ 다운로드 오류:" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Downloading (%s / %s)..." @@ -4089,7 +4089,7 @@ msgstr "í•´ê²° 중..." #: editor/plugins/asset_library_editor_plugin.cpp msgid "Error making request" -msgstr "ìš”ì² ì—러" +msgstr "ìš”ì² ì˜¤ë¥˜" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Idle" @@ -4101,7 +4101,7 @@ msgstr "다시 시ë„" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Download Error" -msgstr "다운로드 ì—러" +msgstr "다운로드 오류" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Download for this asset is already in progress!" @@ -4270,12 +4270,22 @@ msgid "Move CanvasItem" msgstr "CanvasItem ì´ë™" #: editor/plugins/canvas_item_editor_plugin.cpp +msgid "Presets for the anchors and margins values of a Control node." +msgstr "Control ë…¸ë“œì˜ ì•µì»¤ì™€ 여백 ê°’ì˜ í”„ë¦¬ì…‹." + +#: editor/plugins/canvas_item_editor_plugin.cpp +msgid "" +"Children of containers have their anchors and margins values overridden by " +"their parent." +msgstr "컨테ì´ë„ˆì˜ ìžë…€ëŠ” ë¶€ëª¨ì— ì˜í•´ ê·¸ë“¤ì˜ ì•µì»¤ì™€ 여백 ê°’ì´ ìž¬ì •ì˜ë©ë‹ˆë‹¤." + +#: editor/plugins/canvas_item_editor_plugin.cpp msgid "Anchors only" msgstr "앵커만" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Change Anchors and Margins" -msgstr "앵커와 마진 변경" +msgstr "앵커와 여백 변경" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Change Anchors" @@ -4525,7 +4535,7 @@ msgstr "%s 추가" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Adding %s..." -msgstr "%s 추가중..." +msgstr "%s 추가 중..." #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Cannot instantiate multiple nodes without root." @@ -4539,7 +4549,7 @@ msgstr "노드 만들기" #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp msgid "Error instancing scene from %s" -msgstr "'%s' 로부터 씬 ì¸ìŠ¤í„´ìŠ¤ 중 ì—러" +msgstr "'%s'ì—서 씬 ì¸ìŠ¤í„´ìŠ¤ 중 오류" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Change default type" @@ -4912,7 +4922,7 @@ msgstr "ì˜¤ì§ ParticlesMaterial 프로세스 메테리얼 ì•ˆì˜ í¬ì¸íŠ¸ë§Œ ì #: editor/plugins/particles_2d_editor_plugin.cpp msgid "Error loading image:" -msgstr "ì´ë¯¸ì§€ 불러오기 ì—러:" +msgstr "ì´ë¯¸ì§€ 불러오기 오류:" #: editor/plugins/particles_2d_editor_plugin.cpp msgid "No pixels with transparency > 128 in image..." @@ -5003,7 +5013,7 @@ msgstr "ì—미션 소스: " #: editor/plugins/particles_editor_plugin.cpp msgid "A processor material of type 'ParticlesMaterial' is required." -msgstr "'ParticlesMaterial' íƒ€ìž…ì˜ í”„ë¡œì„¸ì„œ ë¨¸í„°ë¦¬ì–¼ì´ í•„ìš”í•©ë‹ˆë‹¤." +msgstr "'ParticlesMaterial' íƒ€ìž…ì˜ í”„ë¡œì„¸ì„œ ë¨¸í‹°ë¦¬ì–¼ì´ í•„ìš”í•©ë‹ˆë‹¤." #: editor/plugins/particles_editor_plugin.cpp msgid "Generating AABB" @@ -5171,6 +5181,12 @@ msgid "Create UV Map" msgstr "UV ë§µ 만들기" #: editor/plugins/polygon_2d_editor_plugin.cpp +msgid "" +"Polygon 2D has internal vertices, so it can no longer be edited in the " +"viewport." +msgstr "" + +#: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Create Polygon & UV" msgstr "í´ë¦¬ê³¤ & UV 만들기" @@ -5337,7 +5353,7 @@ msgstr "ë³¸ì„ í´ë¦¬ê³¤ì— ë™ê¸°í™”" #: editor/plugins/resource_preloader_editor_plugin.cpp msgid "ERROR: Couldn't load resource!" -msgstr "ì—러: 리소스를 불러올 수 없습니다!" +msgstr "오류: 리소스를 불러올 수 없습니다!" #: editor/plugins/resource_preloader_editor_plugin.cpp msgid "Add Resource" @@ -5403,19 +5419,19 @@ msgstr "변경사í•ì„ ì €ìž¥í•˜ê³ ë‹«ê² ìŠµë‹ˆê¹Œ?" #: editor/plugins/script_editor_plugin.cpp msgid "Error writing TextFile:" -msgstr "í…스트 íŒŒì¼ ì“°ê¸° ì—러:" +msgstr "í…스트 íŒŒì¼ ì“°ê¸° 오류:" #: editor/plugins/script_editor_plugin.cpp msgid "Error: could not load file." -msgstr "ì—러: 파ì¼ì„ 불러올 수 ì—†ìŒ." +msgstr "오류: 파ì¼ì„ 불러올 수 ì—†ìŒ." #: editor/plugins/script_editor_plugin.cpp msgid "Error could not load file." -msgstr "ì—러로 파ì¼ì„ 불러올 수 ì—†ìŒ." +msgstr "오류로 파ì¼ì„ 불러올 수 ì—†ìŒ." #: editor/plugins/script_editor_plugin.cpp msgid "Error saving file!" -msgstr "íŒŒì¼ ì €ìž¥ 중 ì—러!" +msgstr "íŒŒì¼ ì €ìž¥ 중 오류!" #: editor/plugins/script_editor_plugin.cpp msgid "Error while saving theme." @@ -5451,11 +5467,11 @@ msgstr "테마 ê°€ì ¸ì˜¤ê¸°" #: editor/plugins/script_editor_plugin.cpp msgid "Error while saving theme" -msgstr "테마 ì €ìž¥ 중 ì—러" +msgstr "테마 ì €ìž¥ 중 오류" #: editor/plugins/script_editor_plugin.cpp msgid "Error saving" -msgstr "ì €ìž¥ 중 ì—러" +msgstr "ì €ìž¥ 중 오류" #: editor/plugins/script_editor_plugin.cpp msgid "Save Theme As..." @@ -5806,7 +5822,7 @@ msgstr "물리ì 본 만들기" #: editor/plugins/skeleton_editor_plugin.cpp msgid "Skeleton" -msgstr "ìŠ¤ì¼ˆë ˆí†¤" +msgstr "ìŠ¤ì¼ˆë ˆí†¤(Skeleton)" #: editor/plugins/skeleton_editor_plugin.cpp msgid "Create physical skeleton" @@ -5878,7 +5894,7 @@ msgstr "ê·¸ë ¤ì§„ 오브ì 트" #: editor/plugins/spatial_editor_plugin.cpp msgid "Material Changes" -msgstr "머터리얼 변경" +msgstr "머티리얼 변경" #: editor/plugins/spatial_editor_plugin.cpp msgid "Shader Changes" @@ -6260,8 +6276,8 @@ msgid "Post" msgstr "Post" #: editor/plugins/spatial_editor_plugin.cpp -msgid "Name-less gizmo" -msgstr "ì´ë¦„없는 기즈모" +msgid "Nameless gizmo" +msgstr "ì´ë¦„없는 오브ì íŠ¸ì˜ ì¤‘ì‹¬ì " #: editor/plugins/sprite_editor_plugin.cpp msgid "Sprite is empty!" @@ -6305,7 +6321,7 @@ msgstr "ì„¤ì •:" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "ERROR: Couldn't load frame resource!" -msgstr "ì—러: í”„ë ˆìž„ 리소스를 불러올 수 없습니다!" +msgstr "오류: í”„ë ˆìž„ 리소스를 불러올 수 없습니다!" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Add Frame" @@ -6336,8 +6352,12 @@ msgid "(empty)" msgstr "(비었ìŒ)" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animations" -msgstr "ì• ë‹ˆë©”ì´ì…˜(Animations)" +msgid "Animations:" +msgstr "ì• ë‹ˆë©”ì´ì…˜:" + +#: editor/plugins/sprite_frames_editor_plugin.cpp +msgid "New Animation" +msgstr "새로운 ì• ë‹ˆë©”ì´ì…˜" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed (FPS):" @@ -6348,8 +6368,8 @@ msgid "Loop" msgstr "루프" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animation Frames" -msgstr "ì• ë‹ˆë©”ì´ì…˜ í”„ë ˆìž„" +msgid "Animation Frames:" +msgstr "ì• ë‹ˆë©”ì´ì…˜ í”„ë ˆìž„:" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Insert Empty (Before)" @@ -6848,7 +6868,7 @@ msgstr "실행가능" #: editor/project_export.cpp msgid "Delete patch '%s' from list?" -msgstr "'%s'를 패치 목ë¡ì—서 ì‚ì œí•˜ì‹œê² ìŠµë‹ˆê¹Œ?" +msgstr "'%s'ì„(를) 패치 목ë¡ì—서 ì‚ì œí•˜ì‹œê² ìŠµë‹ˆê¹Œ?" #: editor/project_export.cpp msgid "Delete preset '%s'?" @@ -7030,7 +7050,7 @@ msgid "" "Couldn't load project.godot in project path (error %d). It may be missing or " "corrupted." msgstr "" -"프로ì 트 경로로부터 project.godot 파ì¼ì„ 불러올 수 없습니다 (ì—러 %d). 존재하" +"프로ì 트 경로로부터 project.godot 파ì¼ì„ 불러올 수 없습니다 (오류 %d). 존재하" "ì§€ 않거나 ì†ìƒë˜ì—ˆì„ 수 있습니다." #: editor/project_manager.cpp @@ -7099,11 +7119,11 @@ msgstr "찾아보기" #: editor/project_manager.cpp msgid "Renderer:" -msgstr "" +msgstr "ë Œë”러:" #: editor/project_manager.cpp msgid "OpenGL ES 3.0" -msgstr "" +msgstr "OpenGL ES 3.0" #: editor/project_manager.cpp msgid "" @@ -7112,10 +7132,14 @@ msgid "" "Incompatible with older hardware\n" "Not recommended for web games" msgstr "" +"ë†’ì€ ì‹œê°ì 품질\n" +"ëª¨ë“ ê¸°ëŠ¥ 사용 가능\n" +"ì˜¤ëž˜ëœ í•˜ë“œì›¨ì–´ì—는 호환하지 않ìŒ\n" +"웹 게임ì—는 비 추천" #: editor/project_manager.cpp msgid "OpenGL ES 2.0" -msgstr "" +msgstr "OpenGL ES 2.0" #: editor/project_manager.cpp msgid "" @@ -7124,10 +7148,14 @@ msgid "" "Works on most hardware\n" "Recommended for web games" msgstr "" +"ë‚®ì€ ì‹œê°ì 품질\n" +"ì¼ë¶€ ê¸°ëŠ¥ì€ ì‚¬ìš©í• ìˆ˜ ì—†ìŒ\n" +"ëŒ€ë¶€ë¶„ì˜ í•˜ë“œì›¨ì–´ì—서 ìž‘ë™í•¨\n" +"웹 ê²Œìž„ì— ì¶”ì²œ" #: editor/project_manager.cpp msgid "Renderer can be changed later, but scenes may need to be adjusted." -msgstr "" +msgstr "ë Œë”러는 ë‚˜ì¤‘ì— ë°”ê¿€ 수 있지만, ì”¬ì„ ì¡°ì •í•´ì•¼ í• ìˆ˜ë„ ìžˆìŠµë‹ˆë‹¤." #: editor/project_manager.cpp msgid "Unnamed Project" @@ -7143,6 +7171,25 @@ msgstr "ë‘ê°œ ì´ìƒì˜ 프로ì 트를 ì—´ë ¤ëŠ” ê²ƒì´ í™•ì‹¤í•©ë‹ˆê¹Œ?" #: editor/project_manager.cpp msgid "" +"The following project settings file does not specify the version of Godot " +"through which it was created.\n" +"\n" +"%s\n" +"\n" +"If you proceed with opening it, it will be converted to Godot's current " +"configuration file format.\n" +"Warning: You will not be able to open the project with previous versions of " +"the engine anymore." +msgstr "" +"ë‹¤ìŒ í”„ë¡œì 트 ì„¤ì • 파ì¼ì€ ì´ ë²„ì „ì˜ Godot로 ìƒì„±ë˜ì§€ 않았습니다.\n" +"↵\n" +"%s↵\n" +"↵\n" +"파ì¼ì„ 연다면, 현재 Godotì˜ êµ¬ì„± íŒŒì¼ í˜•ì‹ìœ¼ë¡œ 변환ë©ë‹ˆë‹¤.\n" +"ê²½ê³ : ì´ì „ ë²„ì „ì˜ ì—”ì§„ìœ¼ë¡œ ë” ì´ìƒ ì—´ 수 없게 ë 것입니다." + +#: editor/project_manager.cpp +msgid "" "The following project settings file was generated by an older engine " "version, and needs to be converted for this version:\n" "\n" @@ -7152,13 +7199,13 @@ msgid "" "Warning: You will not be able to open the project with previous versions of " "the engine anymore." msgstr "" -"다ìŒì˜ 프로ì 트 ì„¤ì • 파ì¼ì€ ì˜ˆì „ ë²„ì „ì—서 ìƒì„±ëœ 것으로, ì´ ë²„ì „ì— ë§žê²Œ ì „í™˜" -"해야 합니다:\n" +"다ìŒì˜ 프로ì 트 ì„¤ì • 파ì¼ì€ ì´ì „ ë²„ì „ì—서 ìƒì„±ëœ 것으로, ë‹¤ìŒ ë²„ì „ì— ë§žê²Œ ë³€" +"환해야 합니다:\n" "\n" "%s\n" "\n" -"ì „í™˜í•˜ì‹œê² ìŠµë‹ˆê¹Œ?\n" -"ê²½ê³ : ë” ì´ìƒ ì´ í”„ë¡œì 트를 과거 ë²„ì „ì˜ ê²ƒìœ¼ë¡œ ì—´ 수 없게 ë©ë‹ˆë‹¤." +"ë³€í™˜í•˜ì‹œê² ìŠµë‹ˆê¹Œ?\n" +"ê²½ê³ : ë” ì´ìƒ ì´ í”„ë¡œì 트를 ì´ì „ ë²„ì „ì—서 ì—´ 수 없게 ë©ë‹ˆë‹¤." #: editor/project_manager.cpp msgid "" @@ -7207,7 +7254,7 @@ msgstr "" msgid "" "You are about the scan %s folders for existing Godot projects. Do you " "confirm?" -msgstr "%s ì—서 기존 Godot 프로ì íŠ¸ë“¤ì„ ìŠ¤ìº”í•˜ë ¤ê³ í•©ë‹ˆë‹¤. ì§„í–‰í•˜ì‹œê² ìŠµë‹ˆê¹Œ?" +msgstr "%sì—서 기존 Godot 프로ì íŠ¸ë“¤ì„ ìŠ¤ìº”í•˜ë ¤ê³ í•©ë‹ˆë‹¤. ì§„í–‰í•˜ì‹œê² ìŠµë‹ˆê¹Œ?" #: editor/project_manager.cpp msgid "Project Manager" @@ -7279,7 +7326,7 @@ msgstr "" #: editor/project_settings_editor.cpp msgid "Action '%s' already exists!" -msgstr "'%s' ì•¡ì…˜ì´ ì´ë¯¸ 존재합니다!" +msgstr "ì•¡ì…˜ '%s'ì´(ê°€) ì´ë¯¸ 존재합니다!" #: editor/project_settings_editor.cpp msgid "Rename Input Action Event" @@ -7419,7 +7466,7 @@ msgstr "'%s' ì†ì„±ì´ 존재하지 않습니다." #: editor/project_settings_editor.cpp msgid "Setting '%s' is internal, and it can't be deleted." -msgstr "'%s' ì„¤ì •ì€ ë‚´ë¶€ì ì¸ ê²ƒìž…ë‹ˆë‹¤, ì‚ì œê°€ 불가합니다." +msgstr "'%s' ì„¤ì •ì€ ë‚´ë¶€ì ì¸ ê²ƒìž…ë‹ˆë‹¤, ì‚ì œí• ìˆ˜ 없습니다." #: editor/project_settings_editor.cpp msgid "Delete Item" @@ -7443,7 +7490,7 @@ msgstr "ìž…ë ¥ ì•¡ì…˜ 추가" #: editor/project_settings_editor.cpp msgid "Error saving settings." -msgstr "ì„¤ì • ì €ìž¥ 중 ì—러." +msgstr "ì„¤ì • ì €ìž¥ 중 오류." #: editor/project_settings_editor.cpp msgid "Settings saved OK." @@ -7619,7 +7666,7 @@ msgstr "노드 ì„ íƒ" #: editor/property_editor.cpp msgid "Error loading file: Not a resource!" -msgstr "íŒŒì¼ ë¶ˆëŸ¬ì˜¤ê¸° ì—러: 리소스가 아닙니다!" +msgstr "íŒŒì¼ ë¶ˆëŸ¬ì˜¤ê¸° 오류: 리소스가 아닙니다!" #: editor/property_editor.cpp msgid "Pick a Node" @@ -7767,15 +7814,15 @@ msgstr "리셋" #: editor/rename_dialog.cpp msgid "Error" -msgstr "ì—러" +msgstr "오류" #: editor/reparent_dialog.cpp editor/scene_tree_dock.cpp msgid "Reparent Node" -msgstr "부모노드 ìž¬ì§€ì •" +msgstr "부모 노드 ìž¬ì§€ì •" #: editor/reparent_dialog.cpp msgid "Reparent Location (Select new Parent):" -msgstr "부모노드 ìž¬ì§€ì • 위치 (새 부모 노드를 ì„ íƒ):" +msgstr "부모 노드 ìž¬ì§€ì • 위치 (새 부모 노드를 ì„ íƒ):" #: editor/reparent_dialog.cpp msgid "Keep Global Transform" @@ -7783,7 +7830,7 @@ msgstr "글로벌 변형 ìœ ì§€" #: editor/reparent_dialog.cpp editor/scene_tree_dock.cpp msgid "Reparent" -msgstr "부모노드 ìž¬ì§€ì •" +msgstr "부모 ìž¬ì§€ì •" #: editor/run_settings_dialog.cpp msgid "Run Mode:" @@ -7811,13 +7858,14 @@ msgstr "ì”¬ì„ ì¸ìŠ¤í„´ìŠ¤í• ìˆ˜ 있는 부모가 없습니다." #: editor/scene_tree_dock.cpp msgid "Error loading scene from %s" -msgstr "'%s' 로부터 씬 로딩 중 ì—러" +msgstr "%sì—서 씬 로딩 중 오류" #: editor/scene_tree_dock.cpp msgid "" "Cannot instance the scene '%s' because the current scene exists within one " "of its nodes." -msgstr "ë…¸ë“œì¤‘ì— í˜„ìž¬ ì”¬ì´ ì¡´ìž¬í•˜ê¸° 때문ì—, '%s' ì”¬ì„ ì¸ìŠ¤í„´ìŠ¤ í• ìˆ˜ 없습니다." +msgstr "" +"한 ë…¸ë“œì— í˜„ìž¬ ì”¬ì´ ì¡´ìž¬í•˜ê¸° 때문ì—, '%s' ì”¬ì„ ì¸ìŠ¤í„´ìŠ¤ í• ìˆ˜ 없습니다." #: editor/scene_tree_dock.cpp msgid "Instance Scene(s)" @@ -7850,6 +7898,8 @@ msgstr "노드 ë³µì œ" #: editor/scene_tree_dock.cpp msgid "Can't reparent nodes in inherited scenes, order of nodes can't change." msgstr "" +"ìƒì†ëœ 씬ì—서 부모 노드를 다시 ì§€ì •í• ìˆ˜ 없습니다, ë…¸ë“œì˜ ìˆœì„œëŠ” 바꿀 수 없습" +"니다." #: editor/scene_tree_dock.cpp msgid "Node must belong to the edited scene to become root." @@ -7940,11 +7990,11 @@ msgstr "" #: editor/scene_tree_dock.cpp msgid "Error saving scene." -msgstr "씬 ì €ìž¥ 중 ì—러." +msgstr "씬 ì €ìž¥ 중 오류." #: editor/scene_tree_dock.cpp msgid "Error duplicating scene to save it." -msgstr "ì €ìž¥í•˜ê¸° 위해 ì”¬ì„ ë³µì œí•˜ëŠ” ì¤‘ì— ì—러가 ë°œìƒí–ˆìŠµë‹ˆë‹¤." +msgstr "ì €ìž¥í•˜ê¸° 위해 ì”¬ì„ ë³µì œí•˜ëŠ” ì¤‘ì— ì˜¤ë¥˜ê°€ ë°œìƒí–ˆìŠµë‹ˆë‹¤." #: editor/scene_tree_dock.cpp msgid "Sub-Resources" @@ -8111,15 +8161,15 @@ msgstr "노드 ì„ íƒ" #: editor/script_create_dialog.cpp msgid "Error loading template '%s'" -msgstr "'%s' 템플릿 불러오기 ì—러" +msgstr "'%s' 템플릿 불러오기 오류" #: editor/script_create_dialog.cpp msgid "Error - Could not create script in filesystem." -msgstr "ì—러 - íŒŒì¼ ì‹œìŠ¤í…œì— ìŠ¤í¬ë¦½íŠ¸ë¥¼ ìƒì„±í• 수 없습니다." +msgstr "오류 - íŒŒì¼ ì‹œìŠ¤í…œì— ìŠ¤í¬ë¦½íŠ¸ë¥¼ ìƒì„±í• 수 없습니다." #: editor/script_create_dialog.cpp msgid "Error loading script from %s" -msgstr "'%s' 스í¬ë¦½íЏ 로딩 중 ì—러" +msgstr "'%s' 스í¬ë¦½íЏ 로딩 중 오류" #: editor/script_create_dialog.cpp msgid "N/A" @@ -8235,7 +8285,7 @@ msgstr "목ë¡ì—서 한 ê°œ í˜¹ì€ ì—¬ëŸ¬ ê°œì˜ í•ëª©ì„ ì§‘ì–´ 그래프로 #: editor/script_editor_debugger.cpp modules/mono/editor/mono_bottom_panel.cpp msgid "Errors" -msgstr "ì—러" +msgstr "오류" #: editor/script_editor_debugger.cpp msgid "Child Process Connected" @@ -8243,7 +8293,7 @@ msgstr "ìžì‹ 프로세스 ì—°ê²°ë¨" #: editor/script_editor_debugger.cpp msgid "Copy Error" -msgstr "복사 ì—러" +msgstr "복사 오류" #: editor/script_editor_debugger.cpp msgid "Inspect Previous Instance" @@ -8664,10 +8714,6 @@ msgid "Build Project" msgstr "프로ì 트 빌드" #: modules/mono/editor/mono_bottom_panel.cpp -msgid "Warnings" -msgstr "ê²½ê³ " - -#: modules/mono/editor/mono_bottom_panel.cpp msgid "View log" msgstr "로그 보기" @@ -8847,8 +8893,8 @@ msgstr "비주얼 스í¬ë¦½íЏ 노드 ë³µì œ" #: modules/visual_script/visual_script_editor.cpp msgid "Hold %s to drop a Getter. Hold Shift to drop a generic signature." msgstr "" -"%s 를 ëˆ„ë¥´ê³ ìžˆìœ¼ë©´ Getter를 드ë¡í•©ë‹ˆë‹¤. Shift를 ëˆ„ë¥´ê³ ìžˆìœ¼ë©´ ì¼ë°˜ì ì¸ ì‹œê·¸" -"니처를 드ë¡í•©ë‹ˆë‹¤." +"%sì„(를) ëˆ„ë¥´ê³ ìžˆìœ¼ë©´ Getter를 드ë¡í•©ë‹ˆë‹¤. Shiftì„(를) ëˆ„ë¥´ê³ ìžˆìœ¼ë©´ ì¼ë°˜ì " +"ì¸ ì‹œê·¸ë‹ˆì²˜ë¥¼ 드ë¡í•©ë‹ˆë‹¤." #: modules/visual_script/visual_script_editor.cpp msgid "Hold Ctrl to drop a Getter. Hold Shift to drop a generic signature." @@ -8858,7 +8904,7 @@ msgstr "" #: modules/visual_script/visual_script_editor.cpp msgid "Hold %s to drop a simple reference to the node." -msgstr "%s 를 ëˆ„ë¥´ê³ ìžˆìœ¼ë©´ ë…¸ë“œì— ëŒ€í•œ 간단한 참조를 드ë¡í•©ë‹ˆë‹¤." +msgstr "%sì„(를) ëˆ„ë¥´ê³ ìžˆìœ¼ë©´ ë…¸ë“œì— ëŒ€í•œ 간단한 참조를 드ë¡í•©ë‹ˆë‹¤." #: modules/visual_script/visual_script_editor.cpp msgid "Hold Ctrl to drop a simple reference to the node." @@ -8866,7 +8912,7 @@ msgstr "Ctrlì„ ëˆ„ë¥´ê³ ìžˆìœ¼ë©´ ë…¸ë“œì— ëŒ€í•œ 간단한 참조를 드ë¡í #: modules/visual_script/visual_script_editor.cpp msgid "Hold %s to drop a Variable Setter." -msgstr "%s를 ëˆ„ë¥´ê³ ìžˆë¥´ë©´ 변수 Setter를 드ë¡í•©ë‹ˆë‹¤." +msgstr "%sì„(를) ëˆ„ë¥´ê³ ìžˆë¥´ë©´ 변수 Setter를 드ë¡í•©ë‹ˆë‹¤." #: modules/visual_script/visual_script_editor.cpp msgid "Hold Ctrl to drop a Variable Setter." @@ -9026,7 +9072,7 @@ msgstr "노드를 ì§€ì¹í•˜ëŠ” 경로가 아닙니다!" #: modules/visual_script/visual_script_func_nodes.cpp msgid "Invalid index property name '%s' in node %s." -msgstr "노드 %s ì•ˆì— ì¸ë±ìФ ì†ì„± ì´ë¦„ '%s' 는 ìœ íš¨í•˜ì§€ 않습니다." +msgstr "노드 %s ì•ˆì— ì¸ë±ìФ ì†ì„± ì´ë¦„ '%s'ì€(는) ìœ íš¨í•˜ì§€ 않습니다." #: modules/visual_script/visual_script_nodes.cpp msgid ": Invalid argument of type: " @@ -9079,7 +9125,8 @@ msgstr "패키지 세그먼트는 길ì´ê°€ 0ì´ ì•„ë‹ˆì–´ì•¼ 합니다." #: platform/android/export/export.cpp msgid "The character '%s' is not allowed in Android application package names." -msgstr "ë¬¸ìž '%s' 는 안드로ì´ë“œ ì• í”Œë¦¬ì¼€ì´ì…˜ 패키지 ì´ë¦„으로 쓸 수 없습니다." +msgstr "" +"ë¬¸ìž '%s'ì€(는) 안드로ì´ë“œ ì• í”Œë¦¬ì¼€ì´ì…˜ 패키지 ì´ë¦„으로 쓸 수 없습니다." #: platform/android/export/export.cpp msgid "A digit cannot be the first character in a package segment." @@ -9087,7 +9134,7 @@ msgstr "숫ìžëŠ” 패키지 ì„¸ê·¸ë¨¼íŠ¸ì˜ ì²« 문ìžê°€ ë 수 없습니다." #: platform/android/export/export.cpp msgid "The character '%s' cannot be the first character in a package segment." -msgstr "ë¬¸ìž '%s' 는 패키지 ì„¸ê·¸ë¨¼íŠ¸ì˜ ì²« 문ìžê°€ ë 수 없습니다." +msgstr "ë¬¸ìž '%s'ì€(는) 패키지 ì„¸ê·¸ë¨¼íŠ¸ì˜ ì²« 문ìžê°€ ë 수 없습니다." #: platform/android/export/export.cpp msgid "The package must have at least one '.' separator." @@ -9123,7 +9170,7 @@ msgstr "ì‹ë³„ìž ì„¸ê·¸ë¨¼íŠ¸ëŠ” 길ì´ê°€ 0ì´ ì•„ë‹ˆì–´ì•¼ 합니다." #: platform/iphone/export/export.cpp msgid "The character '%s' is not allowed in Identifier." -msgstr "ë¬¸ìž '%s' 는 ì‹ë³„ìžì— 쓸 수 없습니다." +msgstr "ë¬¸ìž '%s'ì€(는) ì‹ë³„ìžì— 쓸 수 없습니다." #: platform/iphone/export/export.cpp msgid "A digit cannot be the first character in a Identifier segment." @@ -9132,7 +9179,7 @@ msgstr "숫ìžëŠ” ì‹ë³„ìž ì„¸ê·¸ë¨¼íŠ¸ì˜ ì²« 문ìžê°€ ë 수 없습니다." #: platform/iphone/export/export.cpp msgid "" "The character '%s' cannot be the first character in a Identifier segment." -msgstr "ë¬¸ìž '%s' 는 ì‹ë³„ìž ì„¸ê·¸ë¨¼íŠ¸ì˜ ì²« 문ìžê°€ ë 수 없습니다." +msgstr "ë¬¸ìž '%s'ì€(는) ì‹ë³„ìž ì„¸ê·¸ë¨¼íŠ¸ì˜ ì²« 문ìžê°€ ë 수 없습니다." #: platform/iphone/export/export.cpp msgid "The Identifier must have at least one '.' separator." @@ -9332,6 +9379,16 @@ msgid "" msgstr "" "ParallaxLayer는 ParallaxBackground ë…¸ë“œì˜ ìžì‹ë…¸ë“œë¡œ ìžˆì„ ë•Œë§Œ ë™ìž‘합니다." +#: scene/2d/particles_2d.cpp +msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles2D node instead. You can use the \"Convert to " +"CPUParticles\" option for this purpose." +msgstr "" +"GPU 기반 파티í´ì€ GLES2 비디오 드ë¼ì´ë²„ì—서 ì§€ì›í•˜ì§€ 않습니다.\n" +"CPUParticles2D 노드를 사용하세요. ì´ ê²½ìš° \"CPU파티í´ë¡œ 변환\" ì˜µì…˜ì„ ì‚¬ìš©í• " +"수 있습니다." + #: scene/2d/particles_2d.cpp scene/3d/particles.cpp msgid "" "A material to process the particles is not assigned, so no behavior is " @@ -9516,6 +9573,16 @@ msgstr "" #: scene/3d/particles.cpp msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles node instead. You can use the \"Convert to CPUParticles" +"\" option for this purpose." +msgstr "" +"GPU 기반 파티í´ì€ GLES2 비디오 드ë¼ì´ë²„ì—서 ì§€ì›í•˜ì§€ 않습니다.\n" +"CPUParticles 노드를 사용하세요. ì´ ê²½ìš° \"CPU파티í´ë¡œ 변환\" ì˜µì…˜ì„ ì‚¬ìš©í• " +"수 있습니다." + +#: scene/3d/particles.cpp +msgid "" "Nothing is visible because meshes have not been assigned to draw passes." msgstr "ë©”ì‹œë“¤ì„ íŒ¨ìŠ¤ë¥¼ 그리ë„ë¡ í• ë‹¹í•˜ì§€ 않았으므로 ë³´ì´ì§€ 않습니다." @@ -9553,23 +9620,6 @@ msgstr "" msgid "Path property must point to a valid Spatial node to work." msgstr "Path ì†ì„±ì€ ìœ íš¨í•œ Spatial 노드를 가리켜야 합니다." -#: scene/3d/scenario_fx.cpp -msgid "WorldEnvironment needs an Environment resource." -msgstr "WorldEnvironment는 Environment 리소스가 필요합니다." - -#: scene/3d/scenario_fx.cpp -msgid "" -"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." -msgstr "씬마다 WorldEnvironmentê°€ 단 하나만 허용ë©ë‹ˆë‹¤." - -#: scene/3d/scenario_fx.cpp -msgid "" -"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " -"this environment's Background Mode to Canvas (for 2D scenes)." -msgstr "" -"ì´ WorldEnvironment는 무시ë©ë‹ˆë‹¤. (3D ì”¬ì„ ìœ„í•´) Camera를 추가하거나 아니면 " -"(2D ì”¬ì„ ìœ„í•´) ì´ í™˜ê²½ì˜ ë°°ê²½ 모드를 Canvas로 ì„¤ì •í•˜ì„¸ìš”." - #: scene/3d/soft_body.cpp msgid "This body will be ignored until you set a mesh" msgstr "ì´ ë°”ë””ëŠ” 메시를 ì„¤ì •í• ë•Œ 까지 무시ë©ë‹ˆë‹¤" @@ -9599,9 +9649,26 @@ msgstr "" "VehicleWheelì€ VehicleBody로 íœ ì‹œìŠ¤í…œì„ ì œê³µí•˜ëŠ” ê¸°ëŠ¥ì„ í•©ë‹ˆë‹¤. VehicleBody" "ì˜ ìžì‹ìœ¼ë¡œ 사용해주세요." +#: scene/3d/world_environment.cpp +msgid "WorldEnvironment needs an Environment resource." +msgstr "WorldEnvironment는 Environment 리소스가 필요합니다." + +#: scene/3d/world_environment.cpp +msgid "" +"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." +msgstr "씬마다 WorldEnvironmentê°€ 단 하나만 허용ë©ë‹ˆë‹¤." + +#: scene/3d/world_environment.cpp +msgid "" +"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " +"this environment's Background Mode to Canvas (for 2D scenes)." +msgstr "" +"ì´ WorldEnvironment는 무시ë©ë‹ˆë‹¤. (3D ì”¬ì„ ìœ„í•´) Camera를 추가하거나 아니면 " +"(2D ì”¬ì„ ìœ„í•´) ì´ í™˜ê²½ì˜ ë°°ê²½ 모드를 Canvas로 ì„¤ì •í•˜ì„¸ìš”." + #: scene/animation/animation_blend_tree.cpp msgid "On BlendTree node '%s', animation not found: '%s'" -msgstr "BlendTree 노드 '%s' ì—서, ì• ë‹ˆë©”ì´ì…˜ì„ ì°¾ì„ ìˆ˜ ì—†ìŒ: '%s'" +msgstr "BlendTree 노드 '%s'ì—서, ì• ë‹ˆë©”ì´ì…˜ì„ ì°¾ì„ ìˆ˜ ì—†ìŒ: '%s'" #: scene/animation/animation_blend_tree.cpp msgid "Animation not found: '%s'" @@ -9609,7 +9676,7 @@ msgstr "ì• ë‹ˆë©”ì´ì…˜ì„ ì°¾ì„ ìˆ˜ ì—†ìŒ: '%s'" #: scene/animation/animation_tree.cpp msgid "In node '%s', invalid animation: '%s'." -msgstr "노드 '%s' ì—서, ìœ íš¨í•˜ì§€ ì•Šì€ ì• ë‹ˆë©”ì´ì…˜: '%s'." +msgstr "노드 '%s'ì—서, ìœ íš¨í•˜ì§€ ì•Šì€ ì• ë‹ˆë©”ì´ì…˜: '%s'." #: scene/animation/animation_tree.cpp msgid "Invalid animation: '%s'." @@ -9617,7 +9684,7 @@ msgstr "ìœ íš¨í•˜ì§€ ì•Šì€ ì• ë‹ˆë©”ì´ì…˜: '%s'." #: scene/animation/animation_tree.cpp msgid "Nothing connected to input '%s' of node '%s'." -msgstr "노드 '%s' ì˜ '%s' ìž…ë ¥ì— ì•„ë¬´ê²ƒë„ ì—°ê²°ë˜ì§€ 않ìŒ." +msgstr "노드 '%s'ì˜ '%s' ìž…ë ¥ì— ì•„ë¬´ê²ƒë„ ì—°ê²°ë˜ì§€ 않ìŒ." #: scene/animation/animation_tree.cpp msgid "A root AnimationNode for the graph is not set." @@ -9644,11 +9711,20 @@ msgstr "" "ì´ ë…¸ë“œëŠ” ë” ì´ìƒ ì‚¬ìš©í• ìˆ˜ 없습니다. AnimationTree를 사용하시길 ë°”ëžë‹ˆë‹¤." #: scene/gui/color_picker.cpp +msgid "Pick a color from the screen." +msgstr "화면ì—서 색ìƒì„ ì„ íƒí•˜ì„¸ìš”." + +#: scene/gui/color_picker.cpp msgid "Raw Mode" msgstr "Raw 모드" #: scene/gui/color_picker.cpp -msgid "Add current color as a preset" +msgid "Switch between hexadecimal and code values." +msgstr "16 진수나 코드 값으로 ì „í™˜í•©ë‹ˆë‹¤." + +#: scene/gui/color_picker.cpp +#, fuzzy +msgid "Add current color as a preset." msgstr "현재 색ìƒì„ 프리셋으로 추가" #: scene/gui/dialogs.cpp @@ -9708,7 +9784,7 @@ msgstr "" #: scene/resources/dynamic_font.cpp msgid "Error initializing FreeType." -msgstr "FreeType 초기화 ì—러." +msgstr "FreeType 초기화 오류." #: scene/resources/dynamic_font.cpp msgid "Unknown font format." @@ -9716,7 +9792,7 @@ msgstr "알 수 없는 í°íЏ 형ì‹." #: scene/resources/dynamic_font.cpp msgid "Error loading font." -msgstr "í°íЏ 로딩 ì—러." +msgstr "í°íЏ 로딩 오류." #: scene/resources/dynamic_font.cpp msgid "Invalid font size." @@ -9742,6 +9818,18 @@ msgstr "ê· ì¼í•˜ê²Œ 배치함." msgid "Varyings can only be assigned in vertex function." msgstr "Varyings는 ì˜¤ì§ ë²„í…스 함수ì—서만 ì§€ì •í• ìˆ˜ 있습니다." +#~ msgid "Warnings:" +#~ msgstr "ê²½ê³ :" + +#~ msgid "Font Size:" +#~ msgstr "í°íЏ í¬ê¸°:" + +#~ msgid "Line:" +#~ msgstr "ë¼ì¸:" + +#~ msgid "Col:" +#~ msgstr "칼럼:" + #~ msgid "OrientedPathFollow only works when set as a child of a Path node." #~ msgstr "OrientedPathFollow는 Path ë…¸ë“œì˜ ìžì‹ìœ¼ë¡œ ìžˆì„ ë•Œë§Œ ë™ìž‘합니다." diff --git a/editor/translations/lt.po b/editor/translations/lt.po index 72c804b3d3..4985518381 100644 --- a/editor/translations/lt.po +++ b/editor/translations/lt.po @@ -547,22 +547,14 @@ msgstr "Nutolinti" msgid "Reset Zoom" msgstr "Atstatyti PriartinimÄ…" -#: editor/code_editor.cpp -msgid "Warnings:" +#: editor/code_editor.cpp modules/mono/editor/mono_bottom_panel.cpp +msgid "Warnings" msgstr "" #: editor/code_editor.cpp -msgid "Font Size:" +msgid "Line and column numbers." msgstr "" -#: editor/code_editor.cpp -msgid "Line:" -msgstr "Linija:" - -#: editor/code_editor.cpp -msgid "Col:" -msgstr "Stulpelis:" - #: editor/connections_dialog.cpp msgid "Method in target Node must be specified!" msgstr "Metodas pasirinktame Node turi bÅ«ti nurodytas!" @@ -861,8 +853,8 @@ msgstr "" #: editor/dependency_editor.cpp editor/editor_audio_buses.cpp #: editor/editor_file_dialog.cpp editor/editor_node.cpp #: editor/filesystem_dock.cpp editor/plugins/item_list_editor_plugin.cpp -#: editor/project_export.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_dock.cpp +#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp +#: editor/project_settings_editor.cpp editor/scene_tree_dock.cpp msgid "Delete" msgstr "" @@ -1114,7 +1106,7 @@ msgid "Add Bus" msgstr "" #: editor/editor_audio_buses.cpp -msgid "Create a new Bus Layout." +msgid "Add a new Audio Bus to this layout." msgstr "" #: editor/editor_audio_buses.cpp editor/editor_properties.cpp @@ -1143,6 +1135,10 @@ msgstr "" msgid "Load the default Bus Layout." msgstr "" +#: editor/editor_audio_buses.cpp +msgid "Create a new Bus Layout." +msgstr "" + #: editor/editor_autoload_settings.cpp msgid "Invalid name." msgstr "" @@ -2324,7 +2320,7 @@ msgid "Save & Restart" msgstr "" #: editor/editor_node.cpp -msgid "Spins when the editor window repaints!" +msgid "Spins when the editor window redraws." msgstr "" #: editor/editor_node.cpp @@ -3386,23 +3382,6 @@ msgid "Create Polygon" msgstr "Keisti Poligono SkalÄ™" #: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Edit Polygon" -msgstr "Priedai" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Insert Point" -msgstr "" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Edit Polygon (Remove Point)" -msgstr "" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Remove Polygon And Point" -msgstr "" - -#: editor/plugins/abstract_polygon_2d_editor.cpp #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #, fuzzy @@ -3421,6 +3400,23 @@ msgstr "" msgid "Erase points." msgstr "" +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Edit Polygon" +msgstr "Priedai" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Insert Point" +msgstr "" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Edit Polygon (Remove Point)" +msgstr "" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Remove Polygon And Point" +msgstr "" + #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #: editor/plugins/animation_player_editor_plugin.cpp @@ -4216,6 +4212,16 @@ msgid "Move CanvasItem" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp +msgid "Presets for the anchors and margins values of a Control node." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp +msgid "" +"Children of containers have their anchors and margins values overridden by " +"their parent." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp msgid "Anchors only" msgstr "" @@ -5115,6 +5121,12 @@ msgid "Create UV Map" msgstr "" #: editor/plugins/polygon_2d_editor_plugin.cpp +msgid "" +"Polygon 2D has internal vertices, so it can no longer be edited in the " +"viewport." +msgstr "" + +#: editor/plugins/polygon_2d_editor_plugin.cpp #, fuzzy msgid "Create Polygon & UV" msgstr "Keisti Poligono SkalÄ™" @@ -6215,7 +6227,7 @@ msgid "Post" msgstr "" #: editor/plugins/spatial_editor_plugin.cpp -msgid "Name-less gizmo" +msgid "Nameless gizmo" msgstr "" #: editor/plugins/sprite_editor_plugin.cpp @@ -6293,8 +6305,14 @@ msgid "(empty)" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animations" -msgstr "" +#, fuzzy +msgid "Animations:" +msgstr "Animacija" + +#: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "New Animation" +msgstr "Animacija" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed (FPS):" @@ -6305,8 +6323,9 @@ msgid "Loop" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animation Frames" -msgstr "" +#, fuzzy +msgid "Animation Frames:" +msgstr "Animacija" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Insert Empty (Before)" @@ -7107,6 +7126,19 @@ msgstr "" #: editor/project_manager.cpp msgid "" +"The following project settings file does not specify the version of Godot " +"through which it was created.\n" +"\n" +"%s\n" +"\n" +"If you proceed with opening it, it will be converted to Godot's current " +"configuration file format.\n" +"Warning: You will not be able to open the project with previous versions of " +"the engine anymore." +msgstr "" + +#: editor/project_manager.cpp +msgid "" "The following project settings file was generated by an older engine " "version, and needs to be converted for this version:\n" "\n" @@ -8595,10 +8627,6 @@ msgid "Build Project" msgstr "" #: modules/mono/editor/mono_bottom_panel.cpp -msgid "Warnings" -msgstr "" - -#: modules/mono/editor/mono_bottom_panel.cpp msgid "View log" msgstr "" @@ -9232,6 +9260,13 @@ msgid "" "ParallaxLayer node only works when set as child of a ParallaxBackground node." msgstr "" +#: scene/2d/particles_2d.cpp +msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles2D node instead. You can use the \"Convert to " +"CPUParticles\" option for this purpose." +msgstr "" + #: scene/2d/particles_2d.cpp scene/3d/particles.cpp msgid "" "A material to process the particles is not assigned, so no behavior is " @@ -9389,6 +9424,13 @@ msgstr "" #: scene/3d/particles.cpp msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles node instead. You can use the \"Convert to CPUParticles" +"\" option for this purpose." +msgstr "" + +#: scene/3d/particles.cpp +msgid "" "Nothing is visible because meshes have not been assigned to draw passes." msgstr "" @@ -9419,21 +9461,6 @@ msgstr "" msgid "Path property must point to a valid Spatial node to work." msgstr "" -#: scene/3d/scenario_fx.cpp -msgid "WorldEnvironment needs an Environment resource." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " -"this environment's Background Mode to Canvas (for 2D scenes)." -msgstr "" - #: scene/3d/soft_body.cpp msgid "This body will be ignored until you set a mesh" msgstr "" @@ -9457,6 +9484,21 @@ msgid "" "it as a child of a VehicleBody." msgstr "" +#: scene/3d/world_environment.cpp +msgid "WorldEnvironment needs an Environment resource." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " +"this environment's Background Mode to Canvas (for 2D scenes)." +msgstr "" + #: scene/animation/animation_blend_tree.cpp msgid "On BlendTree node '%s', animation not found: '%s'" msgstr "" @@ -9503,11 +9545,19 @@ msgid "This node has been deprecated. Use AnimationTree instead." msgstr "" #: scene/gui/color_picker.cpp +msgid "Pick a color from the screen." +msgstr "" + +#: scene/gui/color_picker.cpp msgid "Raw Mode" msgstr "" #: scene/gui/color_picker.cpp -msgid "Add current color as a preset" +msgid "Switch between hexadecimal and code values." +msgstr "" + +#: scene/gui/color_picker.cpp +msgid "Add current color as a preset." msgstr "" #: scene/gui/dialogs.cpp @@ -9591,6 +9641,12 @@ msgstr "" msgid "Varyings can only be assigned in vertex function." msgstr "" +#~ msgid "Line:" +#~ msgstr "Linija:" + +#~ msgid "Col:" +#~ msgstr "Stulpelis:" + #, fuzzy #~ msgid "Remove Split" #~ msgstr "Panaikinti pasirinkimÄ…" diff --git a/editor/translations/lv.po b/editor/translations/lv.po index 6c87d52153..60475bea45 100644 --- a/editor/translations/lv.po +++ b/editor/translations/lv.po @@ -543,22 +543,14 @@ msgstr "AttÄlinÄt" msgid "Reset Zoom" msgstr "AtiestatÄ«t tÄlummaiņu" -#: editor/code_editor.cpp -msgid "Warnings:" +#: editor/code_editor.cpp modules/mono/editor/mono_bottom_panel.cpp +msgid "Warnings" msgstr "" #: editor/code_editor.cpp -msgid "Font Size:" +msgid "Line and column numbers." msgstr "" -#: editor/code_editor.cpp -msgid "Line:" -msgstr "Rinda:" - -#: editor/code_editor.cpp -msgid "Col:" -msgstr "Kolona:" - #: editor/connections_dialog.cpp msgid "Method in target Node must be specified!" msgstr "" @@ -857,8 +849,8 @@ msgstr "IzdzÄ“st izvÄ“lÄ“tos failus?" #: editor/dependency_editor.cpp editor/editor_audio_buses.cpp #: editor/editor_file_dialog.cpp editor/editor_node.cpp #: editor/filesystem_dock.cpp editor/plugins/item_list_editor_plugin.cpp -#: editor/project_export.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_dock.cpp +#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp +#: editor/project_settings_editor.cpp editor/scene_tree_dock.cpp msgid "Delete" msgstr "IzdzÄ“st" @@ -1114,7 +1106,7 @@ msgid "Add Bus" msgstr "Pievienot Kopni" #: editor/editor_audio_buses.cpp -msgid "Create a new Bus Layout." +msgid "Add a new Audio Bus to this layout." msgstr "" #: editor/editor_audio_buses.cpp editor/editor_properties.cpp @@ -1143,6 +1135,10 @@ msgstr "IelÄdÄ“t NoklusÄ“jumu" msgid "Load the default Bus Layout." msgstr "IelÄdÄ“t Kopnes IzkÄrtojuma noklusÄ“jumu." +#: editor/editor_audio_buses.cpp +msgid "Create a new Bus Layout." +msgstr "" + #: editor/editor_autoload_settings.cpp msgid "Invalid name." msgstr "NederÄ«gs nosaukums." @@ -2329,7 +2325,7 @@ msgid "Save & Restart" msgstr "" #: editor/editor_node.cpp -msgid "Spins when the editor window repaints!" +msgid "Spins when the editor window redraws." msgstr "" #: editor/editor_node.cpp @@ -3377,39 +3373,39 @@ msgid "Create Polygon" msgstr "Izveidot" #: editor/plugins/abstract_polygon_2d_editor.cpp +#: editor/plugins/animation_blend_space_1d_editor.cpp +#: editor/plugins/animation_blend_space_2d_editor.cpp #, fuzzy -msgid "Edit Polygon" +msgid "Create points." msgstr "Izveidot" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Insert Point" -msgstr "" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Edit Polygon (Remove Point)" +msgid "" +"Edit points.\n" +"LMB: Move Point\n" +"RMB: Erase Point" msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Remove Polygon And Point" +#: editor/plugins/animation_blend_space_1d_editor.cpp +msgid "Erase points." msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -#: editor/plugins/animation_blend_space_1d_editor.cpp -#: editor/plugins/animation_blend_space_2d_editor.cpp #, fuzzy -msgid "Create points." +msgid "Edit Polygon" msgstr "Izveidot" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "" -"Edit points.\n" -"LMB: Move Point\n" -"RMB: Erase Point" +msgid "Insert Point" msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -#: editor/plugins/animation_blend_space_1d_editor.cpp -msgid "Erase points." +msgid "Edit Polygon (Remove Point)" +msgstr "" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Remove Polygon And Point" msgstr "" #: editor/plugins/animation_blend_space_1d_editor.cpp @@ -4199,6 +4195,16 @@ msgid "Move CanvasItem" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp +msgid "Presets for the anchors and margins values of a Control node." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp +msgid "" +"Children of containers have their anchors and margins values overridden by " +"their parent." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp msgid "Anchors only" msgstr "" @@ -5097,6 +5103,12 @@ msgid "Create UV Map" msgstr "" #: editor/plugins/polygon_2d_editor_plugin.cpp +msgid "" +"Polygon 2D has internal vertices, so it can no longer be edited in the " +"viewport." +msgstr "" + +#: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Create Polygon & UV" msgstr "" @@ -6197,7 +6209,7 @@ msgid "Post" msgstr "" #: editor/plugins/spatial_editor_plugin.cpp -msgid "Name-less gizmo" +msgid "Nameless gizmo" msgstr "" #: editor/plugins/sprite_editor_plugin.cpp @@ -6274,8 +6286,14 @@ msgid "(empty)" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animations" -msgstr "" +#, fuzzy +msgid "Animations:" +msgstr "Funkcijas:" + +#: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "New Animation" +msgstr "OptimizÄ“t animÄciju" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed (FPS):" @@ -6286,8 +6304,9 @@ msgid "Loop" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animation Frames" -msgstr "" +#, fuzzy +msgid "Animation Frames:" +msgstr "AnimÄcijas Ä«pašības." #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Insert Empty (Before)" @@ -7080,6 +7099,19 @@ msgstr "" #: editor/project_manager.cpp msgid "" +"The following project settings file does not specify the version of Godot " +"through which it was created.\n" +"\n" +"%s\n" +"\n" +"If you proceed with opening it, it will be converted to Godot's current " +"configuration file format.\n" +"Warning: You will not be able to open the project with previous versions of " +"the engine anymore." +msgstr "" + +#: editor/project_manager.cpp +msgid "" "The following project settings file was generated by an older engine " "version, and needs to be converted for this version:\n" "\n" @@ -8563,10 +8595,6 @@ msgid "Build Project" msgstr "" #: modules/mono/editor/mono_bottom_panel.cpp -msgid "Warnings" -msgstr "" - -#: modules/mono/editor/mono_bottom_panel.cpp msgid "View log" msgstr "" @@ -9198,6 +9226,13 @@ msgid "" "ParallaxLayer node only works when set as child of a ParallaxBackground node." msgstr "" +#: scene/2d/particles_2d.cpp +msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles2D node instead. You can use the \"Convert to " +"CPUParticles\" option for this purpose." +msgstr "" + #: scene/2d/particles_2d.cpp scene/3d/particles.cpp msgid "" "A material to process the particles is not assigned, so no behavior is " @@ -9353,6 +9388,13 @@ msgstr "" #: scene/3d/particles.cpp msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles node instead. You can use the \"Convert to CPUParticles" +"\" option for this purpose." +msgstr "" + +#: scene/3d/particles.cpp +msgid "" "Nothing is visible because meshes have not been assigned to draw passes." msgstr "" @@ -9383,21 +9425,6 @@ msgstr "" msgid "Path property must point to a valid Spatial node to work." msgstr "" -#: scene/3d/scenario_fx.cpp -msgid "WorldEnvironment needs an Environment resource." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " -"this environment's Background Mode to Canvas (for 2D scenes)." -msgstr "" - #: scene/3d/soft_body.cpp msgid "This body will be ignored until you set a mesh" msgstr "" @@ -9421,6 +9448,21 @@ msgid "" "it as a child of a VehicleBody." msgstr "" +#: scene/3d/world_environment.cpp +msgid "WorldEnvironment needs an Environment resource." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " +"this environment's Background Mode to Canvas (for 2D scenes)." +msgstr "" + #: scene/animation/animation_blend_tree.cpp msgid "On BlendTree node '%s', animation not found: '%s'" msgstr "" @@ -9465,11 +9507,20 @@ msgid "This node has been deprecated. Use AnimationTree instead." msgstr "" #: scene/gui/color_picker.cpp +msgid "Pick a color from the screen." +msgstr "" + +#: scene/gui/color_picker.cpp msgid "Raw Mode" msgstr "" #: scene/gui/color_picker.cpp -msgid "Add current color as a preset" +msgid "Switch between hexadecimal and code values." +msgstr "" + +#: scene/gui/color_picker.cpp +#, fuzzy +msgid "Add current color as a preset." msgstr "Pievienot paÅ¡reizÄ“jo krÄsu kÄ iepriekÅ¡noteiktu krÄsu" #: scene/gui/dialogs.cpp @@ -9553,6 +9604,12 @@ msgstr "" msgid "Varyings can only be assigned in vertex function." msgstr "" +#~ msgid "Line:" +#~ msgstr "Rinda:" + +#~ msgid "Col:" +#~ msgstr "Kolona:" + #, fuzzy #~ msgid "Remove Split" #~ msgstr "Noņemt IzvÄ“lÄ“to" diff --git a/editor/translations/ml.po b/editor/translations/ml.po index 8487b78616..346181c489 100644 --- a/editor/translations/ml.po +++ b/editor/translations/ml.po @@ -532,20 +532,12 @@ msgstr "" msgid "Reset Zoom" msgstr "" -#: editor/code_editor.cpp -msgid "Warnings:" -msgstr "" - -#: editor/code_editor.cpp -msgid "Font Size:" -msgstr "" - -#: editor/code_editor.cpp -msgid "Line:" +#: editor/code_editor.cpp modules/mono/editor/mono_bottom_panel.cpp +msgid "Warnings" msgstr "" #: editor/code_editor.cpp -msgid "Col:" +msgid "Line and column numbers." msgstr "" #: editor/connections_dialog.cpp @@ -839,8 +831,8 @@ msgstr "" #: editor/dependency_editor.cpp editor/editor_audio_buses.cpp #: editor/editor_file_dialog.cpp editor/editor_node.cpp #: editor/filesystem_dock.cpp editor/plugins/item_list_editor_plugin.cpp -#: editor/project_export.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_dock.cpp +#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp +#: editor/project_settings_editor.cpp editor/scene_tree_dock.cpp msgid "Delete" msgstr "" @@ -1092,7 +1084,7 @@ msgid "Add Bus" msgstr "" #: editor/editor_audio_buses.cpp -msgid "Create a new Bus Layout." +msgid "Add a new Audio Bus to this layout." msgstr "" #: editor/editor_audio_buses.cpp editor/editor_properties.cpp @@ -1121,6 +1113,10 @@ msgstr "" msgid "Load the default Bus Layout." msgstr "" +#: editor/editor_audio_buses.cpp +msgid "Create a new Bus Layout." +msgstr "" + #: editor/editor_autoload_settings.cpp msgid "Invalid name." msgstr "" @@ -2291,7 +2287,7 @@ msgid "Save & Restart" msgstr "" #: editor/editor_node.cpp -msgid "Spins when the editor window repaints!" +msgid "Spins when the editor window redraws." msgstr "" #: editor/editor_node.cpp @@ -3329,37 +3325,37 @@ msgid "Create Polygon" msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Edit Polygon" +#: editor/plugins/animation_blend_space_1d_editor.cpp +#: editor/plugins/animation_blend_space_2d_editor.cpp +msgid "Create points." msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Insert Point" +msgid "" +"Edit points.\n" +"LMB: Move Point\n" +"RMB: Erase Point" msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Edit Polygon (Remove Point)" +#: editor/plugins/animation_blend_space_1d_editor.cpp +msgid "Erase points." msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Remove Polygon And Point" +msgid "Edit Polygon" msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -#: editor/plugins/animation_blend_space_1d_editor.cpp -#: editor/plugins/animation_blend_space_2d_editor.cpp -msgid "Create points." +msgid "Insert Point" msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "" -"Edit points.\n" -"LMB: Move Point\n" -"RMB: Erase Point" +msgid "Edit Polygon (Remove Point)" msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -#: editor/plugins/animation_blend_space_1d_editor.cpp -msgid "Erase points." +msgid "Remove Polygon And Point" msgstr "" #: editor/plugins/animation_blend_space_1d_editor.cpp @@ -4142,6 +4138,16 @@ msgid "Move CanvasItem" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp +msgid "Presets for the anchors and margins values of a Control node." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp +msgid "" +"Children of containers have their anchors and margins values overridden by " +"their parent." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp msgid "Anchors only" msgstr "" @@ -5037,6 +5043,12 @@ msgid "Create UV Map" msgstr "" #: editor/plugins/polygon_2d_editor_plugin.cpp +msgid "" +"Polygon 2D has internal vertices, so it can no longer be edited in the " +"viewport." +msgstr "" + +#: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Create Polygon & UV" msgstr "" @@ -6118,7 +6130,7 @@ msgid "Post" msgstr "" #: editor/plugins/spatial_editor_plugin.cpp -msgid "Name-less gizmo" +msgid "Nameless gizmo" msgstr "" #: editor/plugins/sprite_editor_plugin.cpp @@ -6194,7 +6206,11 @@ msgid "(empty)" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animations" +msgid "Animations:" +msgstr "" + +#: editor/plugins/sprite_frames_editor_plugin.cpp +msgid "New Animation" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp @@ -6206,7 +6222,7 @@ msgid "Loop" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animation Frames" +msgid "Animation Frames:" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp @@ -6982,6 +6998,19 @@ msgstr "" #: editor/project_manager.cpp msgid "" +"The following project settings file does not specify the version of Godot " +"through which it was created.\n" +"\n" +"%s\n" +"\n" +"If you proceed with opening it, it will be converted to Godot's current " +"configuration file format.\n" +"Warning: You will not be able to open the project with previous versions of " +"the engine anymore." +msgstr "" + +#: editor/project_manager.cpp +msgid "" "The following project settings file was generated by an older engine " "version, and needs to be converted for this version:\n" "\n" @@ -8458,10 +8487,6 @@ msgid "Build Project" msgstr "" #: modules/mono/editor/mono_bottom_panel.cpp -msgid "Warnings" -msgstr "" - -#: modules/mono/editor/mono_bottom_panel.cpp msgid "View log" msgstr "" @@ -9087,6 +9112,13 @@ msgid "" "ParallaxLayer node only works when set as child of a ParallaxBackground node." msgstr "" +#: scene/2d/particles_2d.cpp +msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles2D node instead. You can use the \"Convert to " +"CPUParticles\" option for this purpose." +msgstr "" + #: scene/2d/particles_2d.cpp scene/3d/particles.cpp msgid "" "A material to process the particles is not assigned, so no behavior is " @@ -9242,6 +9274,13 @@ msgstr "" #: scene/3d/particles.cpp msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles node instead. You can use the \"Convert to CPUParticles" +"\" option for this purpose." +msgstr "" + +#: scene/3d/particles.cpp +msgid "" "Nothing is visible because meshes have not been assigned to draw passes." msgstr "" @@ -9272,21 +9311,6 @@ msgstr "" msgid "Path property must point to a valid Spatial node to work." msgstr "" -#: scene/3d/scenario_fx.cpp -msgid "WorldEnvironment needs an Environment resource." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " -"this environment's Background Mode to Canvas (for 2D scenes)." -msgstr "" - #: scene/3d/soft_body.cpp msgid "This body will be ignored until you set a mesh" msgstr "" @@ -9310,6 +9334,21 @@ msgid "" "it as a child of a VehicleBody." msgstr "" +#: scene/3d/world_environment.cpp +msgid "WorldEnvironment needs an Environment resource." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " +"this environment's Background Mode to Canvas (for 2D scenes)." +msgstr "" + #: scene/animation/animation_blend_tree.cpp msgid "On BlendTree node '%s', animation not found: '%s'" msgstr "" @@ -9351,11 +9390,19 @@ msgid "This node has been deprecated. Use AnimationTree instead." msgstr "" #: scene/gui/color_picker.cpp +msgid "Pick a color from the screen." +msgstr "" + +#: scene/gui/color_picker.cpp msgid "Raw Mode" msgstr "" #: scene/gui/color_picker.cpp -msgid "Add current color as a preset" +msgid "Switch between hexadecimal and code values." +msgstr "" + +#: scene/gui/color_picker.cpp +msgid "Add current color as a preset." msgstr "" #: scene/gui/dialogs.cpp diff --git a/editor/translations/ms.po b/editor/translations/ms.po index d384ae1e44..a336b59d6f 100644 --- a/editor/translations/ms.po +++ b/editor/translations/ms.po @@ -541,20 +541,12 @@ msgstr "" msgid "Reset Zoom" msgstr "" -#: editor/code_editor.cpp -msgid "Warnings:" -msgstr "" - -#: editor/code_editor.cpp -msgid "Font Size:" -msgstr "" - -#: editor/code_editor.cpp -msgid "Line:" +#: editor/code_editor.cpp modules/mono/editor/mono_bottom_panel.cpp +msgid "Warnings" msgstr "" #: editor/code_editor.cpp -msgid "Col:" +msgid "Line and column numbers." msgstr "" #: editor/connections_dialog.cpp @@ -848,8 +840,8 @@ msgstr "" #: editor/dependency_editor.cpp editor/editor_audio_buses.cpp #: editor/editor_file_dialog.cpp editor/editor_node.cpp #: editor/filesystem_dock.cpp editor/plugins/item_list_editor_plugin.cpp -#: editor/project_export.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_dock.cpp +#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp +#: editor/project_settings_editor.cpp editor/scene_tree_dock.cpp msgid "Delete" msgstr "" @@ -1101,7 +1093,7 @@ msgid "Add Bus" msgstr "" #: editor/editor_audio_buses.cpp -msgid "Create a new Bus Layout." +msgid "Add a new Audio Bus to this layout." msgstr "" #: editor/editor_audio_buses.cpp editor/editor_properties.cpp @@ -1130,6 +1122,10 @@ msgstr "" msgid "Load the default Bus Layout." msgstr "" +#: editor/editor_audio_buses.cpp +msgid "Create a new Bus Layout." +msgstr "" + #: editor/editor_autoload_settings.cpp msgid "Invalid name." msgstr "" @@ -2300,7 +2296,7 @@ msgid "Save & Restart" msgstr "" #: editor/editor_node.cpp -msgid "Spins when the editor window repaints!" +msgid "Spins when the editor window redraws." msgstr "" #: editor/editor_node.cpp @@ -3338,37 +3334,37 @@ msgid "Create Polygon" msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Edit Polygon" +#: editor/plugins/animation_blend_space_1d_editor.cpp +#: editor/plugins/animation_blend_space_2d_editor.cpp +msgid "Create points." msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Insert Point" +msgid "" +"Edit points.\n" +"LMB: Move Point\n" +"RMB: Erase Point" msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Edit Polygon (Remove Point)" +#: editor/plugins/animation_blend_space_1d_editor.cpp +msgid "Erase points." msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Remove Polygon And Point" +msgid "Edit Polygon" msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -#: editor/plugins/animation_blend_space_1d_editor.cpp -#: editor/plugins/animation_blend_space_2d_editor.cpp -msgid "Create points." +msgid "Insert Point" msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "" -"Edit points.\n" -"LMB: Move Point\n" -"RMB: Erase Point" +msgid "Edit Polygon (Remove Point)" msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -#: editor/plugins/animation_blend_space_1d_editor.cpp -msgid "Erase points." +msgid "Remove Polygon And Point" msgstr "" #: editor/plugins/animation_blend_space_1d_editor.cpp @@ -4153,6 +4149,16 @@ msgid "Move CanvasItem" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp +msgid "Presets for the anchors and margins values of a Control node." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp +msgid "" +"Children of containers have their anchors and margins values overridden by " +"their parent." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp msgid "Anchors only" msgstr "" @@ -5048,6 +5054,12 @@ msgid "Create UV Map" msgstr "" #: editor/plugins/polygon_2d_editor_plugin.cpp +msgid "" +"Polygon 2D has internal vertices, so it can no longer be edited in the " +"viewport." +msgstr "" + +#: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Create Polygon & UV" msgstr "" @@ -6129,7 +6141,7 @@ msgid "Post" msgstr "" #: editor/plugins/spatial_editor_plugin.cpp -msgid "Name-less gizmo" +msgid "Nameless gizmo" msgstr "" #: editor/plugins/sprite_editor_plugin.cpp @@ -6205,7 +6217,12 @@ msgid "(empty)" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animations" +#, fuzzy +msgid "Animations:" +msgstr "Set Peralihan ke:" + +#: editor/plugins/sprite_frames_editor_plugin.cpp +msgid "New Animation" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp @@ -6217,7 +6234,7 @@ msgid "Loop" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animation Frames" +msgid "Animation Frames:" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp @@ -6998,6 +7015,19 @@ msgstr "" #: editor/project_manager.cpp msgid "" +"The following project settings file does not specify the version of Godot " +"through which it was created.\n" +"\n" +"%s\n" +"\n" +"If you proceed with opening it, it will be converted to Godot's current " +"configuration file format.\n" +"Warning: You will not be able to open the project with previous versions of " +"the engine anymore." +msgstr "" + +#: editor/project_manager.cpp +msgid "" "The following project settings file was generated by an older engine " "version, and needs to be converted for this version:\n" "\n" @@ -8478,10 +8508,6 @@ msgid "Build Project" msgstr "" #: modules/mono/editor/mono_bottom_panel.cpp -msgid "Warnings" -msgstr "" - -#: modules/mono/editor/mono_bottom_panel.cpp msgid "View log" msgstr "" @@ -9107,6 +9133,13 @@ msgid "" "ParallaxLayer node only works when set as child of a ParallaxBackground node." msgstr "" +#: scene/2d/particles_2d.cpp +msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles2D node instead. You can use the \"Convert to " +"CPUParticles\" option for this purpose." +msgstr "" + #: scene/2d/particles_2d.cpp scene/3d/particles.cpp msgid "" "A material to process the particles is not assigned, so no behavior is " @@ -9262,6 +9295,13 @@ msgstr "" #: scene/3d/particles.cpp msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles node instead. You can use the \"Convert to CPUParticles" +"\" option for this purpose." +msgstr "" + +#: scene/3d/particles.cpp +msgid "" "Nothing is visible because meshes have not been assigned to draw passes." msgstr "" @@ -9292,21 +9332,6 @@ msgstr "" msgid "Path property must point to a valid Spatial node to work." msgstr "" -#: scene/3d/scenario_fx.cpp -msgid "WorldEnvironment needs an Environment resource." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " -"this environment's Background Mode to Canvas (for 2D scenes)." -msgstr "" - #: scene/3d/soft_body.cpp msgid "This body will be ignored until you set a mesh" msgstr "" @@ -9330,6 +9355,21 @@ msgid "" "it as a child of a VehicleBody." msgstr "" +#: scene/3d/world_environment.cpp +msgid "WorldEnvironment needs an Environment resource." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " +"this environment's Background Mode to Canvas (for 2D scenes)." +msgstr "" + #: scene/animation/animation_blend_tree.cpp msgid "On BlendTree node '%s', animation not found: '%s'" msgstr "" @@ -9371,11 +9411,19 @@ msgid "This node has been deprecated. Use AnimationTree instead." msgstr "" #: scene/gui/color_picker.cpp +msgid "Pick a color from the screen." +msgstr "" + +#: scene/gui/color_picker.cpp msgid "Raw Mode" msgstr "" #: scene/gui/color_picker.cpp -msgid "Add current color as a preset" +msgid "Switch between hexadecimal and code values." +msgstr "" + +#: scene/gui/color_picker.cpp +msgid "Add current color as a preset." msgstr "" #: scene/gui/dialogs.cpp diff --git a/editor/translations/nb.po b/editor/translations/nb.po index 933d2f0ed9..ada2ff1569 100644 --- a/editor/translations/nb.po +++ b/editor/translations/nb.po @@ -5,10 +5,10 @@ # Allan Nordhøy <epost@anotheragency.no>, 2017-2018. # Anonymous <GentleSaucepan@protonmail.com>, 2017. # Elias <eliasnykrem@gmail.com>, 2018. -# flesk <eivindkn@gmail.com>, 2017. +# flesk <eivindkn@gmail.com>, 2017, 2019. # Frank T. Rambol <frank@d-fect.com>, 2018. # Jørgen Aarmo Lund <jorgen.aarmo@gmail.com>, 2016. -# NicolaiF <nico-fre@hotmail.com>, 2017-2018. +# NicolaiF <nico-fre@hotmail.com>, 2017-2018, 2019. # Norwegian Disaster <stian.furu.overbye@gmail.com>, 2017. # passeride <lukas@passeride.com>, 2017. # Byzantin <kasper-hoel@hotmail.com>, 2018. @@ -16,8 +16,8 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2018-12-13 14:41+0100\n" -"Last-Translator: Allan Nordhøy <epost@anotheragency.no>\n" +"PO-Revision-Date: 2019-02-13 16:10+0000\n" +"Last-Translator: NicolaiF <nico-fre@hotmail.com>\n" "Language-Team: Norwegian BokmÃ¥l <https://hosted.weblate.org/projects/godot-" "engine/godot/nb_NO/>\n" "Language: nb\n" @@ -25,7 +25,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Poedit 2.2\n" +"X-Generator: Weblate 3.5-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -126,24 +126,29 @@ msgid "Anim Change Call" msgstr "Anim Forandre Kall" #: editor/animation_track_editor.cpp +#, fuzzy msgid "Property Track" -msgstr "" +msgstr "Egenskapsspor" #: editor/animation_track_editor.cpp +#, fuzzy msgid "3D Transform Track" -msgstr "" +msgstr "3D transformasjonsspor" #: editor/animation_track_editor.cpp +#, fuzzy msgid "Call Method Track" -msgstr "" +msgstr "Kall metode-spor" #: editor/animation_track_editor.cpp +#, fuzzy msgid "Bezier Curve Track" -msgstr "" +msgstr "Bezier-kurvespor" #: editor/animation_track_editor.cpp +#, fuzzy msgid "Audio Playback Track" -msgstr "" +msgstr "Lydavspillingsspor" #: editor/animation_track_editor.cpp #, fuzzy @@ -172,11 +177,12 @@ msgstr "Funksjoner:" #: editor/animation_track_editor.cpp msgid "Audio Clips:" -msgstr "" +msgstr "Lydklipp:" #: editor/animation_track_editor.cpp +#, fuzzy msgid "Anim Clips:" -msgstr "" +msgstr "Anim-klipp:" #: editor/animation_track_editor.cpp #, fuzzy @@ -185,7 +191,7 @@ msgstr "Vis/skjul distraksjonsfri modus." #: editor/animation_track_editor.cpp msgid "Update Mode (How this property is set)" -msgstr "" +msgstr "Oppdateringsmodus (Hvordan denne egenskapen settes)" #: editor/animation_track_editor.cpp #, fuzzy @@ -225,7 +231,7 @@ msgstr "Framtid" #: editor/animation_track_editor.cpp msgid "Nearest" -msgstr "" +msgstr "Nærmeste" #: editor/animation_track_editor.cpp editor/plugins/curve_editor_plugin.cpp #: editor/property_editor.cpp @@ -234,7 +240,7 @@ msgstr "Lineær" #: editor/animation_track_editor.cpp msgid "Cubic" -msgstr "" +msgstr "Kubisk" #: editor/animation_track_editor.cpp msgid "Clamp Loop Interp" @@ -286,7 +292,7 @@ msgstr "Anim Sett inn" #: editor/animation_track_editor.cpp msgid "AnimationPlayer can't animate itself, only other players." -msgstr "" +msgstr "AnimasjonAvspiller kan ikke animere seg selv, kun andre avspillere." #: editor/animation_track_editor.cpp msgid "Anim Create & Insert" @@ -301,8 +307,9 @@ msgid "Anim Insert Key" msgstr "Anim Sett Inn Nøkkel" #: editor/animation_track_editor.cpp +#, fuzzy msgid "Transform tracks only apply to Spatial-based nodes." -msgstr "" +msgstr "Transformasjonsspor kan kun brukes pÃ¥ Spatial-baserte noder." #: editor/animation_track_editor.cpp msgid "" @@ -311,34 +318,44 @@ msgid "" "-AudioStreamPlayer2D\n" "-AudioStreamPlayer3D" msgstr "" +"Lydspor kan kun peke pÃ¥ noder av type:\n" +"-AudioStreamPlayer\n" +"-AudioStreamPlayer2D\n" +"-AudioStreamPlayer3D" #: editor/animation_track_editor.cpp +#, fuzzy msgid "Animation tracks can only point to AnimationPlayer nodes." -msgstr "" +msgstr "Animasjonsspor kan kun peke pÃ¥ AnimationPlayer-noder." #: editor/animation_track_editor.cpp msgid "An animation player can't animate itself, only other players." msgstr "" +"En animansjonsavspiller kan ikke animere seg selv, kun andre avspillere." #: editor/animation_track_editor.cpp +#, fuzzy msgid "Not possible to add a new track without a root" -msgstr "" +msgstr "Ikke mulig Ã¥ legge til et nytt spor uten en rot" #: editor/animation_track_editor.cpp +#, fuzzy msgid "Track path is invalid, so can't add a key." -msgstr "" +msgstr "Sporsti er ugyldig, sÃ¥ kan ikke legge til en nøkkel." #: editor/animation_track_editor.cpp +#, fuzzy msgid "Track is not of type Spatial, can't insert key" -msgstr "" +msgstr "Spor er ikke av type Spatial, kan ikke legge til nøkkel" #: editor/animation_track_editor.cpp +#, fuzzy msgid "Track path is invalid, so can't add a method key." -msgstr "" +msgstr "Sporsti er ugyldig, sÃ¥ kan ikke legge til metodenøkkel." #: editor/animation_track_editor.cpp msgid "Method not found in object: " -msgstr "" +msgstr "Metode ikke funnet i objekt: " #: editor/animation_track_editor.cpp msgid "Anim Move Keys" @@ -354,17 +371,20 @@ msgid "Anim Scale Keys" msgstr "Anim Skalér Nøkler" #: editor/animation_track_editor.cpp +#, fuzzy msgid "" "This option does not work for Bezier editing, as it's only a single track." msgstr "" +"Dette valget virker ikke pÃ¥ Bezier-redigering, siden det kun er ett enkelt " +"spor." #: editor/animation_track_editor.cpp msgid "Only show tracks from nodes selected in tree." -msgstr "" +msgstr "Vis kun spor fra noder valgt i treet." #: editor/animation_track_editor.cpp msgid "Group tracks by node or display them as plain list." -msgstr "" +msgstr "Grupper spor etter node eller vis dem i en enkel liste." #: editor/animation_track_editor.cpp #, fuzzy @@ -441,11 +461,11 @@ msgstr "Rydd-Opp-Animasjon" #: editor/animation_track_editor.cpp msgid "Pick the node that will be animated:" -msgstr "" +msgstr "Velg noden som skal animeres:" #: editor/animation_track_editor.cpp msgid "Use Bezier Curves" -msgstr "" +msgstr "Bruk Bezier-kurver" #: editor/animation_track_editor.cpp msgid "Anim. Optimizer" @@ -493,7 +513,7 @@ msgstr "Skaler Størrelsesforhold:" #: editor/animation_track_editor.cpp msgid "Select tracks to copy:" -msgstr "" +msgstr "Velg spor Ã¥ kopiere:" #: editor/animation_track_editor.cpp editor/editor_properties.cpp #: editor/plugins/animation_player_editor_plugin.cpp @@ -567,22 +587,13 @@ msgstr "Zoom Ut" msgid "Reset Zoom" msgstr "Nullstill Zoom" -#: editor/code_editor.cpp -msgid "Warnings:" -msgstr "" - -#: editor/code_editor.cpp -#, fuzzy -msgid "Font Size:" -msgstr "Frontvisning" - -#: editor/code_editor.cpp -msgid "Line:" -msgstr "Linje:" +#: editor/code_editor.cpp modules/mono/editor/mono_bottom_panel.cpp +msgid "Warnings" +msgstr "Advarsler" #: editor/code_editor.cpp -msgid "Col:" -msgstr "Kol:" +msgid "Line and column numbers." +msgstr "" #: editor/connections_dialog.cpp msgid "Method in target Node must be specified!" @@ -701,6 +712,7 @@ msgstr "Signaler" #: editor/connections_dialog.cpp msgid "Are you sure you want to remove all connections from this signal?" msgstr "" +"Er du sikker pÃ¥ at du ønsker Ã¥ fjerne alle koblinger fra dette signalet?" #: editor/connections_dialog.cpp #, fuzzy @@ -892,8 +904,8 @@ msgstr "Slett valgte filer?" #: editor/dependency_editor.cpp editor/editor_audio_buses.cpp #: editor/editor_file_dialog.cpp editor/editor_node.cpp #: editor/filesystem_dock.cpp editor/plugins/item_list_editor_plugin.cpp -#: editor/project_export.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_dock.cpp +#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp +#: editor/project_settings_editor.cpp editor/scene_tree_dock.cpp msgid "Delete" msgstr "Slett" @@ -1152,8 +1164,9 @@ msgid "Add Bus" msgstr "Legg til Bus" #: editor/editor_audio_buses.cpp -msgid "Create a new Bus Layout." -msgstr "Opprett et nytt Bus oppsett." +#, fuzzy +msgid "Add a new Audio Bus to this layout." +msgstr "Lagre Audio Bus Oppsett som..." #: editor/editor_audio_buses.cpp editor/editor_properties.cpp #: editor/plugins/animation_player_editor_plugin.cpp editor/property_editor.cpp @@ -1181,6 +1194,10 @@ msgstr "Last Standard" msgid "Load the default Bus Layout." msgstr "Last standard Bus oppsettet." +#: editor/editor_audio_buses.cpp +msgid "Create a new Bus Layout." +msgstr "Opprett et nytt Bus oppsett." + #: editor/editor_autoload_settings.cpp msgid "Invalid name." msgstr "Ugyldig navn." @@ -1320,8 +1337,9 @@ msgid "Storing File:" msgstr "Lagrer Fil:" #: editor/editor_export.cpp +#, fuzzy msgid "No export template found at the expected path:" -msgstr "" +msgstr "Ingen eksportmal funnet pÃ¥ forventet søkesti:" #: editor/editor_export.cpp msgid "Packing" @@ -1337,8 +1355,9 @@ msgstr "Malfil ble ikke funnet:" #: editor/editor_export.cpp platform/android/export/export.cpp #: platform/iphone/export/export.cpp platform/javascript/export/export.cpp #: platform/osx/export/export.cpp platform/uwp/export/export.cpp +#, fuzzy msgid "Custom release template not found." -msgstr "" +msgstr "Tilpasset utgivelsesmal ikke funnet." #: editor/editor_export.cpp platform/javascript/export/export.cpp msgid "Template file not found:" @@ -1506,7 +1525,7 @@ msgstr "Egenskaper" #: editor/editor_help.cpp msgid "Properties:" -msgstr "" +msgstr "Egenskaper:" #: editor/editor_help.cpp msgid "Methods" @@ -1663,15 +1682,16 @@ msgstr "Klasse:" #: editor/editor_inspector.cpp editor/project_settings_editor.cpp msgid "Property:" -msgstr "" +msgstr "Egenskap:" #: editor/editor_inspector.cpp msgid "Set" msgstr "Sett" #: editor/editor_inspector.cpp +#, fuzzy msgid "Set Multiple:" -msgstr "" +msgstr "Sett Mange:" #: editor/editor_log.cpp msgid "Output:" @@ -1702,7 +1722,7 @@ msgstr "Feil ved lagring av ressurs!" #: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp #: scene/gui/dialogs.cpp msgid "OK" -msgstr "" +msgstr "OK" #: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp msgid "Save Resource As..." @@ -1722,7 +1742,7 @@ msgstr "Feil under lagring." #: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp msgid "Can't open '%s'. The file could have been moved or deleted." -msgstr "" +msgstr "Kan ikke Ã¥pne '%s'. Filen kan ha blitt flyttet eller slettet." #: editor/editor_node.cpp msgid "Error while parsing '%s'." @@ -1757,10 +1777,14 @@ msgid "This operation can't be done without a tree root." msgstr "Denne operasjonen kan ikke gjennomføres uten en trerot." #: editor/editor_node.cpp +#, fuzzy msgid "" "This scene can't be saved because there is a cyclic instancing inclusion.\n" "Please resolve it and then attempt to save again." msgstr "" +"Denne scenen kan ikke lagres fordi det er en sirkulær " +"instansieringsinklusjon.\n" +"Vennligst løs feilen og forsøk Ã¥ lagre igjen." #: editor/editor_node.cpp msgid "" @@ -1772,7 +1796,7 @@ msgstr "" #: editor/editor_node.cpp editor/scene_tree_dock.cpp msgid "Can't overwrite scene that is still open!" -msgstr "" +msgstr "Kan ikke overskrive en scene som fortsatt er Ã¥pen!" #: editor/editor_node.cpp msgid "Can't load MeshLibrary for merging!" @@ -2446,8 +2470,9 @@ msgid "Play Custom Scene" msgstr "Spill av Tilpasset Scene" #: editor/editor_node.cpp +#, fuzzy msgid "Changing the video driver requires restarting the editor." -msgstr "" +msgstr "Endring av videodriver krever omstart av redigeringsverktøyet." #: editor/editor_node.cpp editor/project_settings_editor.cpp #: editor/settings_config_dialog.cpp @@ -2457,7 +2482,7 @@ msgstr "Lagre & Avslutt" #: editor/editor_node.cpp #, fuzzy -msgid "Spins when the editor window repaints!" +msgid "Spins when the editor window redraws." msgstr "Snurrer nÃ¥r editorvinduet rendrer om!" #: editor/editor_node.cpp @@ -2659,23 +2684,23 @@ msgstr "Ring" #: editor/editor_properties.cpp msgid "On" -msgstr "" +msgstr "PÃ¥" #: editor/editor_properties.cpp msgid "Layer" -msgstr "" +msgstr "Lag" #: editor/editor_properties.cpp msgid "Bit %d, value %d" -msgstr "" +msgstr "Bit %d, verdi %d" #: editor/editor_properties.cpp msgid "[Empty]" -msgstr "" +msgstr "[Tom]" #: editor/editor_properties.cpp editor/plugins/root_motion_editor_plugin.cpp msgid "Assign..." -msgstr "" +msgstr "Tilordne..." #: editor/editor_properties.cpp #, fuzzy @@ -2683,16 +2708,22 @@ msgid "Invalid RID" msgstr ": Ugyldige argumenter: " #: editor/editor_properties.cpp +#, fuzzy msgid "" "The selected resource (%s) does not match any type expected for this " "property (%s)." msgstr "" +"Den valgte ressursen (%s) svarer ikke til noen forventede verdier for denne " +"egenskapen (%s)." #: editor/editor_properties.cpp +#, fuzzy msgid "" "Can't create a ViewportTexture on resources saved as a file.\n" "Resource needs to belong to a scene." msgstr "" +"Kan ikke opprette en ViewportTexture pÃ¥ ressurser lagret som fil.\n" +"Ressurser mÃ¥ tilhøre en scene." #: editor/editor_properties.cpp msgid "" @@ -2708,15 +2739,15 @@ msgstr "" #: editor/editor_properties.cpp editor/property_editor.cpp msgid "New Script" -msgstr "" +msgstr "Nytt Skript" #: editor/editor_properties.cpp editor/property_editor.cpp msgid "New %s" -msgstr "" +msgstr "Ny %s" #: editor/editor_properties.cpp editor/property_editor.cpp msgid "Make Unique" -msgstr "" +msgstr "Gjør Unik" #: editor/editor_properties.cpp #: editor/plugins/animation_blend_space_1d_editor.cpp @@ -2734,7 +2765,7 @@ msgstr "Lim inn" #: editor/editor_properties.cpp editor/property_editor.cpp msgid "Convert To %s" -msgstr "" +msgstr "Konverter Til %s" #: editor/editor_properties.cpp #: editor/plugins/animation_blend_space_1d_editor.cpp @@ -2750,11 +2781,11 @@ msgstr "" #: editor/editor_properties_array_dict.cpp msgid "Size: " -msgstr "" +msgstr "Størrelse: " #: editor/editor_properties_array_dict.cpp msgid "Page: " -msgstr "" +msgstr "Side: " #: editor/editor_properties_array_dict.cpp #, fuzzy @@ -3562,7 +3593,7 @@ msgstr "" #: editor/plugin_config_dialog.cpp msgid "Language:" -msgstr "" +msgstr "SprÃ¥k:" #: editor/plugin_config_dialog.cpp #, fuzzy @@ -3571,7 +3602,7 @@ msgstr "Prosjektnavn:" #: editor/plugin_config_dialog.cpp msgid "Activate now?" -msgstr "" +msgstr "Aktiver nÃ¥?" #: editor/plugins/abstract_polygon_2d_editor.cpp #: editor/plugins/polygon_2d_editor_plugin.cpp @@ -3580,25 +3611,6 @@ msgid "Create Polygon" msgstr "Lag Poly" #: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Edit Polygon" -msgstr "Rediger Poly" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Insert Point" -msgstr "Sett inn Punkt" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Edit Polygon (Remove Point)" -msgstr "Rediger Poly (Fjern Punkt)" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Remove Polygon And Point" -msgstr "Fjern Poly Og Punkt" - -#: editor/plugins/abstract_polygon_2d_editor.cpp #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #, fuzzy @@ -3623,6 +3635,25 @@ msgstr "" msgid "Erase points." msgstr "Høyreklikk: Slett Punkt." +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Edit Polygon" +msgstr "Rediger Poly" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Insert Point" +msgstr "Sett inn Punkt" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Edit Polygon (Remove Point)" +msgstr "Rediger Poly (Fjern Punkt)" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Remove Polygon And Point" +msgstr "Fjern Poly Og Punkt" + #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #: editor/plugins/animation_player_editor_plugin.cpp @@ -4297,7 +4328,7 @@ msgstr "Neste" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Last" -msgstr "" +msgstr "Siste" #: editor/plugins/asset_library_editor_plugin.cpp #: modules/gdnative/gdnative_library_editor_plugin.cpp @@ -4448,6 +4479,16 @@ msgid "Move CanvasItem" msgstr "Endre CanvasItem" #: editor/plugins/canvas_item_editor_plugin.cpp +msgid "Presets for the anchors and margins values of a Control node." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp +msgid "" +"Children of containers have their anchors and margins values overridden by " +"their parent." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp msgid "Anchors only" msgstr "Kun anker" @@ -4640,7 +4681,7 @@ msgstr "Fjern Ben" #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp msgid "View" -msgstr "Vis" +msgstr "Visning" #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/polygon_2d_editor_plugin.cpp @@ -5378,6 +5419,12 @@ msgid "Create UV Map" msgstr "" #: editor/plugins/polygon_2d_editor_plugin.cpp +msgid "" +"Polygon 2D has internal vertices, so it can no longer be edited in the " +"viewport." +msgstr "" + +#: editor/plugins/polygon_2d_editor_plugin.cpp #, fuzzy msgid "Create Polygon & UV" msgstr "Lag Poly" @@ -5496,7 +5543,7 @@ msgstr "" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Radius:" -msgstr "" +msgstr "Radius:" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Polygon->UV" @@ -6521,7 +6568,7 @@ msgid "Post" msgstr "" #: editor/plugins/spatial_editor_plugin.cpp -msgid "Name-less gizmo" +msgid "Nameless gizmo" msgstr "" #: editor/plugins/sprite_editor_plugin.cpp @@ -6601,10 +6648,16 @@ msgid "(empty)" msgstr "(tom)" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animations" +#, fuzzy +msgid "Animations:" msgstr "Animasjoner" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "New Animation" +msgstr "Animasjon" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed (FPS):" msgstr "Hastighet (FPS):" @@ -6613,8 +6666,9 @@ msgid "Loop" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animation Frames" -msgstr "" +#, fuzzy +msgid "Animation Frames:" +msgstr "Animasjonsnavn:" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Insert Empty (Before)" @@ -7443,6 +7497,19 @@ msgstr "Er du sikker pÃ¥ at du vil Ã¥pne mer enn ett prosjekt?" #: editor/project_manager.cpp msgid "" +"The following project settings file does not specify the version of Godot " +"through which it was created.\n" +"\n" +"%s\n" +"\n" +"If you proceed with opening it, it will be converted to Godot's current " +"configuration file format.\n" +"Warning: You will not be able to open the project with previous versions of " +"the engine anymore." +msgstr "" + +#: editor/project_manager.cpp +msgid "" "The following project settings file was generated by an older engine " "version, and needs to be converted for this version:\n" "\n" @@ -8977,10 +9044,6 @@ msgid "Build Project" msgstr "Prosjekt" #: modules/mono/editor/mono_bottom_panel.cpp -msgid "Warnings" -msgstr "" - -#: modules/mono/editor/mono_bottom_panel.cpp #, fuzzy msgid "View log" msgstr "Vis Filer" @@ -9637,6 +9700,13 @@ msgid "" "ParallaxLayer node only works when set as child of a ParallaxBackground node." msgstr "" +#: scene/2d/particles_2d.cpp +msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles2D node instead. You can use the \"Convert to " +"CPUParticles\" option for this purpose." +msgstr "" + #: scene/2d/particles_2d.cpp scene/3d/particles.cpp msgid "" "A material to process the particles is not assigned, so no behavior is " @@ -9792,6 +9862,13 @@ msgstr "" #: scene/3d/particles.cpp msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles node instead. You can use the \"Convert to CPUParticles" +"\" option for this purpose." +msgstr "" + +#: scene/3d/particles.cpp +msgid "" "Nothing is visible because meshes have not been assigned to draw passes." msgstr "" @@ -9822,21 +9899,6 @@ msgstr "" msgid "Path property must point to a valid Spatial node to work." msgstr "" -#: scene/3d/scenario_fx.cpp -msgid "WorldEnvironment needs an Environment resource." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " -"this environment's Background Mode to Canvas (for 2D scenes)." -msgstr "" - #: scene/3d/soft_body.cpp msgid "This body will be ignored until you set a mesh" msgstr "" @@ -9860,6 +9922,21 @@ msgid "" "it as a child of a VehicleBody." msgstr "" +#: scene/3d/world_environment.cpp +msgid "WorldEnvironment needs an Environment resource." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " +"this environment's Background Mode to Canvas (for 2D scenes)." +msgstr "" + #: scene/animation/animation_blend_tree.cpp msgid "On BlendTree node '%s', animation not found: '%s'" msgstr "" @@ -9906,11 +9983,19 @@ msgid "This node has been deprecated. Use AnimationTree instead." msgstr "" #: scene/gui/color_picker.cpp +msgid "Pick a color from the screen." +msgstr "" + +#: scene/gui/color_picker.cpp msgid "Raw Mode" msgstr "" #: scene/gui/color_picker.cpp -msgid "Add current color as a preset" +msgid "Switch between hexadecimal and code values." +msgstr "" + +#: scene/gui/color_picker.cpp +msgid "Add current color as a preset." msgstr "" #: scene/gui/dialogs.cpp @@ -9995,6 +10080,19 @@ msgstr "" msgid "Varyings can only be assigned in vertex function." msgstr "" +#~ msgid "Warnings:" +#~ msgstr "Advarsler:" + +#, fuzzy +#~ msgid "Font Size:" +#~ msgstr "Frontvisning" + +#~ msgid "Line:" +#~ msgstr "Linje:" + +#~ msgid "Col:" +#~ msgstr "Kol:" + #, fuzzy #~ msgid "Split already exists." #~ msgstr "Eksisterer allerede" diff --git a/editor/translations/nl.po b/editor/translations/nl.po index 19ef09b17b..7bb0a80b52 100644 --- a/editor/translations/nl.po +++ b/editor/translations/nl.po @@ -572,21 +572,13 @@ msgstr "Uitzoomen" msgid "Reset Zoom" msgstr "Initialiseer Zoom" -#: editor/code_editor.cpp -msgid "Warnings:" -msgstr "Waarschuwingen:" - -#: editor/code_editor.cpp -msgid "Font Size:" -msgstr "Lettertypegrootte:" - -#: editor/code_editor.cpp -msgid "Line:" -msgstr "Regel:" +#: editor/code_editor.cpp modules/mono/editor/mono_bottom_panel.cpp +msgid "Warnings" +msgstr "" #: editor/code_editor.cpp -msgid "Col:" -msgstr "Kolom:" +msgid "Line and column numbers." +msgstr "" #: editor/connections_dialog.cpp msgid "Method in target Node must be specified!" @@ -895,8 +887,8 @@ msgstr "Verwijder geselecteerde bestanden?" #: editor/dependency_editor.cpp editor/editor_audio_buses.cpp #: editor/editor_file_dialog.cpp editor/editor_node.cpp #: editor/filesystem_dock.cpp editor/plugins/item_list_editor_plugin.cpp -#: editor/project_export.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_dock.cpp +#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp +#: editor/project_settings_editor.cpp editor/scene_tree_dock.cpp msgid "Delete" msgstr "Verwijder" @@ -1152,8 +1144,9 @@ msgid "Add Bus" msgstr "Bus Toevoegen" #: editor/editor_audio_buses.cpp -msgid "Create a new Bus Layout." -msgstr "Maak een nieuwe audiobus layout." +#, fuzzy +msgid "Add a new Audio Bus to this layout." +msgstr "Sla Audio Bus Layout Op Als..." #: editor/editor_audio_buses.cpp editor/editor_properties.cpp #: editor/plugins/animation_player_editor_plugin.cpp editor/property_editor.cpp @@ -1181,6 +1174,10 @@ msgstr "Laad Standaard" msgid "Load the default Bus Layout." msgstr "Laad de standaard audiobus layout." +#: editor/editor_audio_buses.cpp +msgid "Create a new Bus Layout." +msgstr "Maak een nieuwe audiobus layout." + #: editor/editor_autoload_settings.cpp msgid "Invalid name." msgstr "Ongeldige naam." @@ -2444,7 +2441,8 @@ msgid "Save & Restart" msgstr "Opslaan & Herstarten" #: editor/editor_node.cpp -msgid "Spins when the editor window repaints!" +#, fuzzy +msgid "Spins when the editor window redraws." msgstr "Draait wanneer het editor venster opnieuw ververst wordt!" #: editor/editor_node.cpp @@ -3507,22 +3505,6 @@ msgid "Create Polygon" msgstr "Veelhoek aanmaken" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Edit Polygon" -msgstr "Veelhoek bewerken" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Insert Point" -msgstr "Punt Toevoegen" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Edit Polygon (Remove Point)" -msgstr "Veelhoek bewerken (punt verwijderen)" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Remove Polygon And Point" -msgstr "Veelhoek en punt verwijderen" - -#: editor/plugins/abstract_polygon_2d_editor.cpp #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp msgid "Create points." @@ -3543,6 +3525,22 @@ msgstr "" msgid "Erase points." msgstr "Punten wissen." +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Edit Polygon" +msgstr "Veelhoek bewerken" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Insert Point" +msgstr "Punt Toevoegen" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Edit Polygon (Remove Point)" +msgstr "Veelhoek bewerken (punt verwijderen)" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Remove Polygon And Point" +msgstr "Veelhoek en punt verwijderen" + #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #: editor/plugins/animation_player_editor_plugin.cpp @@ -4348,6 +4346,19 @@ msgid "Move CanvasItem" msgstr "Verplaats CanvasItem" #: editor/plugins/canvas_item_editor_plugin.cpp +msgid "Presets for the anchors and margins values of a Control node." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp +#, fuzzy +msgid "" +"Children of containers have their anchors and margins values overridden by " +"their parent." +msgstr "" +"Waarschuwing: De positie en grootte van de kinderen van een houder worden " +"alleen door hun ouder bepaald." + +#: editor/plugins/canvas_item_editor_plugin.cpp msgid "Anchors only" msgstr "Alleen Ankers" @@ -5275,6 +5286,12 @@ msgid "Create UV Map" msgstr "Creëer UV Map" #: editor/plugins/polygon_2d_editor_plugin.cpp +msgid "" +"Polygon 2D has internal vertices, so it can no longer be edited in the " +"viewport." +msgstr "" + +#: editor/plugins/polygon_2d_editor_plugin.cpp #, fuzzy msgid "Create Polygon & UV" msgstr "Creëer Poly" @@ -6418,7 +6435,7 @@ msgid "Post" msgstr "Post" #: editor/plugins/spatial_editor_plugin.cpp -msgid "Name-less gizmo" +msgid "Nameless gizmo" msgstr "" #: editor/plugins/sprite_editor_plugin.cpp @@ -6500,10 +6517,16 @@ msgid "(empty)" msgstr "(leeg)" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animations" +#, fuzzy +msgid "Animations:" msgstr "Animaties" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "New Animation" +msgstr "Animatie" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed (FPS):" msgstr "Snelheid (FPS):" @@ -6512,7 +6535,8 @@ msgid "Loop" msgstr "Lus" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animation Frames" +#, fuzzy +msgid "Animation Frames:" msgstr "Animatie Frames" #: editor/plugins/sprite_frames_editor_plugin.cpp @@ -7341,6 +7365,19 @@ msgstr "Weet je zeker dat je meer dan één project wilt openen?" #: editor/project_manager.cpp msgid "" +"The following project settings file does not specify the version of Godot " +"through which it was created.\n" +"\n" +"%s\n" +"\n" +"If you proceed with opening it, it will be converted to Godot's current " +"configuration file format.\n" +"Warning: You will not be able to open the project with previous versions of " +"the engine anymore." +msgstr "" + +#: editor/project_manager.cpp +msgid "" "The following project settings file was generated by an older engine " "version, and needs to be converted for this version:\n" "\n" @@ -8881,10 +8918,6 @@ msgid "Build Project" msgstr "Project" #: modules/mono/editor/mono_bottom_panel.cpp -msgid "Warnings" -msgstr "" - -#: modules/mono/editor/mono_bottom_panel.cpp #, fuzzy msgid "View log" msgstr "Bekijk Bestanden" @@ -9591,6 +9624,13 @@ msgstr "" "ParallaxLayer node werkt alleen wanneer het een kind is van een " "ParallaxBackground node." +#: scene/2d/particles_2d.cpp +msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles2D node instead. You can use the \"Convert to " +"CPUParticles\" option for this purpose." +msgstr "" + #: scene/2d/particles_2d.cpp scene/3d/particles.cpp msgid "" "A material to process the particles is not assigned, so no behavior is " @@ -9761,6 +9801,13 @@ msgstr "" #: scene/3d/particles.cpp msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles node instead. You can use the \"Convert to CPUParticles" +"\" option for this purpose." +msgstr "" + +#: scene/3d/particles.cpp +msgid "" "Nothing is visible because meshes have not been assigned to draw passes." msgstr "" @@ -9793,23 +9840,6 @@ msgid "Path property must point to a valid Spatial node to work." msgstr "" "Pad eigenschap moet verwijzen naar een geldige Spatial node om te werken." -#: scene/3d/scenario_fx.cpp -msgid "WorldEnvironment needs an Environment resource." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." -msgstr "" -"Slechts één WorldEnvironment is toegestaan per scene (of set van " -"geïnstantieerde scenes)." - -#: scene/3d/scenario_fx.cpp -msgid "" -"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " -"this environment's Background Mode to Canvas (for 2D scenes)." -msgstr "" - #: scene/3d/soft_body.cpp msgid "This body will be ignored until you set a mesh" msgstr "" @@ -9835,6 +9865,23 @@ msgid "" "it as a child of a VehicleBody." msgstr "" +#: scene/3d/world_environment.cpp +msgid "WorldEnvironment needs an Environment resource." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." +msgstr "" +"Slechts één WorldEnvironment is toegestaan per scene (of set van " +"geïnstantieerde scenes)." + +#: scene/3d/world_environment.cpp +msgid "" +"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " +"this environment's Background Mode to Canvas (for 2D scenes)." +msgstr "" + #: scene/animation/animation_blend_tree.cpp msgid "On BlendTree node '%s', animation not found: '%s'" msgstr "" @@ -9882,11 +9929,20 @@ msgid "This node has been deprecated. Use AnimationTree instead." msgstr "" #: scene/gui/color_picker.cpp +msgid "Pick a color from the screen." +msgstr "" + +#: scene/gui/color_picker.cpp msgid "Raw Mode" msgstr "Raw-modus" #: scene/gui/color_picker.cpp -msgid "Add current color as a preset" +msgid "Switch between hexadecimal and code values." +msgstr "" + +#: scene/gui/color_picker.cpp +#, fuzzy +msgid "Add current color as a preset." msgstr "Huidige kleur als een preset toevoegen" #: scene/gui/dialogs.cpp @@ -9979,6 +10035,18 @@ msgstr "" msgid "Varyings can only be assigned in vertex function." msgstr "" +#~ msgid "Warnings:" +#~ msgstr "Waarschuwingen:" + +#~ msgid "Font Size:" +#~ msgstr "Lettertypegrootte:" + +#~ msgid "Line:" +#~ msgstr "Regel:" + +#~ msgid "Col:" +#~ msgstr "Kolom:" + #, fuzzy #~ msgid "OrientedPathFollow only works when set as a child of a Path node." #~ msgstr "" diff --git a/editor/translations/pl.po b/editor/translations/pl.po index f4fa56512e..5e3e330c84 100644 --- a/editor/translations/pl.po +++ b/editor/translations/pl.po @@ -16,7 +16,7 @@ # Karol Walasek <coreconviction@gmail.com>, 2016. # Maksymilian Åšwiąć <maksymilian.swiac@gmail.com>, 2017-2018. # Mietek SzczeÅ›niak <ravaging@go2.pl>, 2016. -# NeverK <neverkoxu@gmail.com>, 2018. +# NeverK <neverkoxu@gmail.com>, 2018, 2019. # Rafal Brozio <rafal.brozio@gmail.com>, 2016. # RafaÅ‚ Ziemniak <synaptykq@gmail.com>, 2017. # RM <synaptykq@gmail.com>, 2018. @@ -29,11 +29,12 @@ # Dariusz Siek <dariuszynski@gmail.com>, 2018. # Szymon Nowakowski <smnbdg13@gmail.com>, 2019. # Nie Powiem <blazek10@tlen.pl>, 2019. +# Sebastian Hojka <sibibibi1@gmail.com>, 2019. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2019-01-19 19:22+0000\n" +"PO-Revision-Date: 2019-02-18 08:54+0000\n" "Last-Translator: Tomek <kobewi4e@gmail.com>\n" "Language-Team: Polish <https://hosted.weblate.org/projects/godot-engine/" "godot/pl/>\n" @@ -43,7 +44,7 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " "|| n%100>=20) ? 1 : 2;\n" -"X-Generator: Weblate 3.4-dev\n" +"X-Generator: Weblate 3.5-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -568,21 +569,14 @@ msgstr "Oddal" msgid "Reset Zoom" msgstr "Wyzeruj przybliżenie" -#: editor/code_editor.cpp -msgid "Warnings:" -msgstr "Ostrzeżenia:" - -#: editor/code_editor.cpp -msgid "Font Size:" -msgstr "Rozmiar czcionki:" - -#: editor/code_editor.cpp -msgid "Line:" -msgstr "Linia:" +#: editor/code_editor.cpp modules/mono/editor/mono_bottom_panel.cpp +msgid "Warnings" +msgstr "Ostrzeżenia" #: editor/code_editor.cpp -msgid "Col:" -msgstr "Kolumna:" +#, fuzzy +msgid "Line and column numbers." +msgstr "Numery linii i kolumn" #: editor/connections_dialog.cpp msgid "Method in target Node must be specified!" @@ -883,8 +877,8 @@ msgstr "Usunąć zaznaczone pliki?" #: editor/dependency_editor.cpp editor/editor_audio_buses.cpp #: editor/editor_file_dialog.cpp editor/editor_node.cpp #: editor/filesystem_dock.cpp editor/plugins/item_list_editor_plugin.cpp -#: editor/project_export.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_dock.cpp +#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp +#: editor/project_settings_editor.cpp editor/scene_tree_dock.cpp msgid "Delete" msgstr "UsuÅ„" @@ -1039,7 +1033,6 @@ msgid "Toggle Audio Bus Bypass Effects" msgstr "Przełącz ominiÄ™cie efektów w magistrali audio" #: editor/editor_audio_buses.cpp -#, fuzzy msgid "Select Audio Bus Send" msgstr "Wybierz szynÄ™ wysyÅ‚ki audio" @@ -1141,8 +1134,9 @@ msgid "Add Bus" msgstr "Dodaj magistralÄ™" #: editor/editor_audio_buses.cpp -msgid "Create a new Bus Layout." -msgstr "Utwórz nowy ukÅ‚ad magistral." +#, fuzzy +msgid "Add a new Audio Bus to this layout." +msgstr "Zapisz ukÅ‚ad magistrali audio jako..." #: editor/editor_audio_buses.cpp editor/editor_properties.cpp #: editor/plugins/animation_player_editor_plugin.cpp editor/property_editor.cpp @@ -1170,6 +1164,10 @@ msgstr "Wczytaj domyÅ›lny" msgid "Load the default Bus Layout." msgstr "ZaÅ‚aduj domyÅ›lny ukÅ‚ad magistral." +#: editor/editor_audio_buses.cpp +msgid "Create a new Bus Layout." +msgstr "Utwórz nowy ukÅ‚ad magistral." + #: editor/editor_autoload_settings.cpp msgid "Invalid name." msgstr "NiewÅ‚aÅ›ciwa nazwa." @@ -1308,7 +1306,7 @@ msgstr "Zapisywanie pliku:" #: editor/editor_export.cpp msgid "No export template found at the expected path:" -msgstr "" +msgstr "Nie znaleziono szablonu eksportu w przewidywanej lokalizacji:" #: editor/editor_export.cpp msgid "Packing" @@ -1317,15 +1315,14 @@ msgstr "Pakowanie" #: editor/editor_export.cpp platform/android/export/export.cpp #: platform/iphone/export/export.cpp platform/javascript/export/export.cpp #: platform/osx/export/export.cpp platform/uwp/export/export.cpp -#, fuzzy msgid "Custom debug template not found." -msgstr "Nie znaleziono pliku szablonu:" +msgstr "Nie znaleziono wÅ‚asnego szablonu debugowania." #: editor/editor_export.cpp platform/android/export/export.cpp #: platform/iphone/export/export.cpp platform/javascript/export/export.cpp #: platform/osx/export/export.cpp platform/uwp/export/export.cpp msgid "Custom release template not found." -msgstr "" +msgstr "Nie znaleziono wÅ‚asnego szablonu wydania." #: editor/editor_export.cpp platform/javascript/export/export.cpp msgid "Template file not found:" @@ -1727,6 +1724,8 @@ msgid "" "This scene can't be saved because there is a cyclic instancing inclusion.\n" "Please resolve it and then attempt to save again." msgstr "" +"Ta scena nie może zostać zapisana, ponieważ istnieje cykliczna inkluzja.\n" +"Rozwiąż to i spróbuj zapisać ponownie." #: editor/editor_node.cpp msgid "" @@ -2407,7 +2406,8 @@ msgid "Save & Restart" msgstr "Zapisz i zrestartuj" #: editor/editor_node.cpp -msgid "Spins when the editor window repaints!" +#, fuzzy +msgid "Spins when the editor window redraws." msgstr "Ikona obraca siÄ™, gdy okno edytora jest odrysowywane!" #: editor/editor_node.cpp @@ -2618,15 +2618,16 @@ msgid "Assign..." msgstr "Przypisz..." #: editor/editor_properties.cpp -#, fuzzy msgid "Invalid RID" -msgstr "NieprawidÅ‚owa Å›cieżka" +msgstr "NieprawidÅ‚owy RID" #: editor/editor_properties.cpp msgid "" "The selected resource (%s) does not match any type expected for this " "property (%s)." msgstr "" +"Wybrany zasób (%s) nie zgadza siÄ™ z żadnym rodzajem przewidywanym dla tego " +"użycia (%s)." #: editor/editor_properties.cpp msgid "" @@ -3197,7 +3198,6 @@ msgid "Group name already exists." msgstr "Nazwa grupy już istnieje." #: editor/groups_editor.cpp -#, fuzzy msgid "Invalid group name." msgstr "NiewÅ‚aÅ›ciwa nazwa grupy." @@ -3334,17 +3334,18 @@ msgstr "Importuj ponownie" #: editor/import_dock.cpp msgid "Save scenes, re-import and restart" -msgstr "" +msgstr "Zapisz sceny, re-importuj i zrestartuj" #: editor/import_dock.cpp -#, fuzzy msgid "Changing the type of an imported file requires editor restart." -msgstr "Zmiana sterownika grafiki wymaga restartu edytora." +msgstr "Zmiana rodzaju importowanego pliku wymaga restartu edytora." #: editor/import_dock.cpp msgid "" "WARNING: Assets exist that use this resource, they may stop loading properly." msgstr "" +"OSTRZEÅ»ENIE: Istnieje zawartość używajÄ…ca tego zasobu, która może przestać " +"dziaÅ‚ać prawidÅ‚owo." #: editor/inspector_dock.cpp msgid "Failed to load resource." @@ -3469,32 +3470,12 @@ msgid "Create Polygon" msgstr "Utwórz wielokÄ…t" #: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Edit Polygon" -msgstr "Edytuj wielokÄ…t" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Insert Point" -msgstr "Wstaw punkt" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Edit Polygon (Remove Point)" -msgstr "Edytuj wielokÄ…t (usuÅ„ punkty)" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Remove Polygon And Point" -msgstr "Usuń wielokÄ…t i punkt" - -#: editor/plugins/abstract_polygon_2d_editor.cpp #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp msgid "Create points." msgstr "Utwórz punkty." #: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy msgid "" "Edit points.\n" "LMB: Move Point\n" @@ -3509,6 +3490,22 @@ msgstr "" msgid "Erase points." msgstr "UsuÅ„ punkty." +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Edit Polygon" +msgstr "Edytuj wielokÄ…t" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Insert Point" +msgstr "Wstaw punkt" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Edit Polygon (Remove Point)" +msgstr "Edytuj wielokÄ…t (usuÅ„ punkt)" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Remove Polygon And Point" +msgstr "Usuń wielokÄ…t i punkt" + #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #: editor/plugins/animation_player_editor_plugin.cpp @@ -4316,6 +4313,16 @@ msgid "Move CanvasItem" msgstr "PrzesuÅ„ CanvasItem" #: editor/plugins/canvas_item_editor_plugin.cpp +msgid "Presets for the anchors and margins values of a Control node." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp +msgid "" +"Children of containers have their anchors and margins values overridden by " +"their parent." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp msgid "Anchors only" msgstr "Tylko zakotwiczenia" @@ -5232,6 +5239,12 @@ msgid "Create UV Map" msgstr "Utwórz MapÄ™ UV" #: editor/plugins/polygon_2d_editor_plugin.cpp +msgid "" +"Polygon 2D has internal vertices, so it can no longer be edited in the " +"viewport." +msgstr "" + +#: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Create Polygon & UV" msgstr "Utwórz wielokÄ…t i UV" @@ -6336,7 +6349,7 @@ msgid "Post" msgstr "Po" #: editor/plugins/spatial_editor_plugin.cpp -msgid "Name-less gizmo" +msgid "Nameless gizmo" msgstr "" #: editor/plugins/sprite_editor_plugin.cpp @@ -6413,7 +6426,13 @@ msgid "(empty)" msgstr "(pusty)" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animations" +#, fuzzy +msgid "Animations:" +msgstr "Animacje" + +#: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "New Animation" msgstr "Animacje" #: editor/plugins/sprite_frames_editor_plugin.cpp @@ -6425,7 +6444,8 @@ msgid "Loop" msgstr "PÄ™tla" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animation Frames" +#, fuzzy +msgid "Animation Frames:" msgstr "Klatki animacji" #: editor/plugins/sprite_frames_editor_plugin.cpp @@ -7244,6 +7264,19 @@ msgstr "Czy jesteÅ› pewny że chcesz otworzyć wiÄ™cej niż jeden projekt?" #: editor/project_manager.cpp msgid "" +"The following project settings file does not specify the version of Godot " +"through which it was created.\n" +"\n" +"%s\n" +"\n" +"If you proceed with opening it, it will be converted to Godot's current " +"configuration file format.\n" +"Warning: You will not be able to open the project with previous versions of " +"the engine anymore." +msgstr "" + +#: editor/project_manager.cpp +msgid "" "The following project settings file was generated by an older engine " "version, and needs to be converted for this version:\n" "\n" @@ -8764,10 +8797,6 @@ msgid "Build Project" msgstr "Zbuduj projekt" #: modules/mono/editor/mono_bottom_panel.cpp -msgid "Warnings" -msgstr "Ostrzeżenia" - -#: modules/mono/editor/mono_bottom_panel.cpp msgid "View log" msgstr "Pokaż logi" @@ -8794,7 +8823,7 @@ msgstr "Obliczanie wielkoÅ›ci siatki..." #: modules/recast/navigation_mesh_generator.cpp msgid "Creating heightfield..." -msgstr "" +msgstr "Tworzenie pola wysokoÅ›ci..." #: modules/recast/navigation_mesh_generator.cpp msgid "Marking walkable triangles..." @@ -8802,7 +8831,7 @@ msgstr "Zaznaczanie możliwych do przejÅ›cia trójkÄ…tów ..." #: modules/recast/navigation_mesh_generator.cpp msgid "Constructing compact heightfield..." -msgstr "" +msgstr "Konstruowanie zwartego pola wysokoÅ›ci..." #: modules/recast/navigation_mesh_generator.cpp msgid "Eroding walkable area..." @@ -8954,7 +8983,7 @@ msgstr "" #: modules/visual_script/visual_script_editor.cpp msgid "Hold Ctrl to drop a simple reference to the node." -msgstr "" +msgstr "Przytrzymaj Ctrl, by upuÅ›cić prostÄ… referencjÄ™ do wÄ™zÅ‚a." #: modules/visual_script/visual_script_editor.cpp msgid "Hold %s to drop a Variable Setter." @@ -9450,6 +9479,13 @@ msgstr "" "WÄ™zeÅ‚ typu ParallaxLayer zadziaÅ‚a, jeÅ›li bÄ™dzie dzieckiem wÄ™zÅ‚a " "ParallaxBackground." +#: scene/2d/particles_2d.cpp +msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles2D node instead. You can use the \"Convert to " +"CPUParticles\" option for this purpose." +msgstr "" + #: scene/2d/particles_2d.cpp scene/3d/particles.cpp msgid "" "A material to process the particles is not assigned, so no behavior is " @@ -9643,6 +9679,13 @@ msgstr "" #: scene/3d/particles.cpp msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles node instead. You can use the \"Convert to CPUParticles" +"\" option for this purpose." +msgstr "" + +#: scene/3d/particles.cpp +msgid "" "Nothing is visible because meshes have not been assigned to draw passes." msgstr "" "Nic nie jest widoczne, bo siatki nie zostaÅ‚y przypisane do kolejki rysowania." @@ -9682,25 +9725,6 @@ msgstr "" msgid "Path property must point to a valid Spatial node to work." msgstr "Pole Path musi wskazywać na wÄ™zeÅ‚ Spatial." -#: scene/3d/scenario_fx.cpp -msgid "WorldEnvironment needs an Environment resource." -msgstr "WorldEnvironment wymaga zasobu Environment." - -#: scene/3d/scenario_fx.cpp -msgid "" -"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." -msgstr "" -"Tylko jeden WorldEnvironment jest dozwolony na scenÄ™ (lub zestaw " -"zinstancjonowanych scen)." - -#: scene/3d/scenario_fx.cpp -msgid "" -"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " -"this environment's Background Mode to Canvas (for 2D scenes)." -msgstr "" -"Ten WorldEnvironment jest ignorowany. Dodaj Camera (dla scen 3D) lub ustaw " -"Background Mode tego Å›rodowiska na Canvas (dla scen 2D)." - #: scene/3d/soft_body.cpp msgid "This body will be ignored until you set a mesh" msgstr "To ciaÅ‚o bÄ™dzie ignorowane, dopóki nie ustawisz siatki" @@ -9731,6 +9755,25 @@ msgstr "" "VehicleWheel zapewnia system kół do VehicleBody. ProszÄ™ użyć go jako " "dziedziczÄ…cego po VehicleBody." +#: scene/3d/world_environment.cpp +msgid "WorldEnvironment needs an Environment resource." +msgstr "WorldEnvironment wymaga zasobu Environment." + +#: scene/3d/world_environment.cpp +msgid "" +"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." +msgstr "" +"Tylko jeden WorldEnvironment jest dozwolony na scenÄ™ (lub zestaw " +"zinstancjonowanych scen)." + +#: scene/3d/world_environment.cpp +msgid "" +"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " +"this environment's Background Mode to Canvas (for 2D scenes)." +msgstr "" +"Ten WorldEnvironment jest ignorowany. Dodaj Camera (dla scen 3D) lub ustaw " +"Background Mode tego Å›rodowiska na Canvas (dla scen 2D)." + #: scene/animation/animation_blend_tree.cpp msgid "On BlendTree node '%s', animation not found: '%s'" msgstr "W węźle BlendTree '%s', animacja nie znaleziona: '%s'" @@ -9771,6 +9814,10 @@ msgstr "KorzeÅ„ AnimationPlayer nie jest poprawnym wÄ™zÅ‚em." #: scene/animation/animation_tree_player.cpp msgid "This node has been deprecated. Use AnimationTree instead." +msgstr "Ten wÄ™zeÅ‚ jest przestarzaÅ‚y. Zamiast tego użyj AnimationTree." + +#: scene/gui/color_picker.cpp +msgid "Pick a color from the screen." msgstr "" #: scene/gui/color_picker.cpp @@ -9778,7 +9825,12 @@ msgid "Raw Mode" msgstr "Trybie RAW" #: scene/gui/color_picker.cpp -msgid "Add current color as a preset" +msgid "Switch between hexadecimal and code values." +msgstr "" + +#: scene/gui/color_picker.cpp +#, fuzzy +msgid "Add current color as a preset." msgstr "Dodaj bieżący kolor jako domyÅ›lne" #: scene/gui/dialogs.cpp @@ -9874,6 +9926,18 @@ msgstr "Przypisanie do uniformu." msgid "Varyings can only be assigned in vertex function." msgstr "Varying może być przypisane tylko w funkcji wierzchoÅ‚ków." +#~ msgid "Warnings:" +#~ msgstr "Ostrzeżenia:" + +#~ msgid "Font Size:" +#~ msgstr "Rozmiar czcionki:" + +#~ msgid "Line:" +#~ msgstr "Linia:" + +#~ msgid "Col:" +#~ msgstr "Kolumna:" + #~ msgid "OrientedPathFollow only works when set as a child of a Path node." #~ msgstr "OrientedPathFollow dziaÅ‚a tylko, gdy jest wÄ™zÅ‚em podrzÄ™dnym Path." diff --git a/editor/translations/pr.po b/editor/translations/pr.po index e8240ad087..c52676597c 100644 --- a/editor/translations/pr.po +++ b/editor/translations/pr.po @@ -552,20 +552,12 @@ msgstr "" msgid "Reset Zoom" msgstr "" -#: editor/code_editor.cpp -msgid "Warnings:" -msgstr "" - -#: editor/code_editor.cpp -msgid "Font Size:" -msgstr "" - -#: editor/code_editor.cpp -msgid "Line:" +#: editor/code_editor.cpp modules/mono/editor/mono_bottom_panel.cpp +msgid "Warnings" msgstr "" #: editor/code_editor.cpp -msgid "Col:" +msgid "Line and column numbers." msgstr "" #: editor/connections_dialog.cpp @@ -863,8 +855,8 @@ msgstr "" #: editor/dependency_editor.cpp editor/editor_audio_buses.cpp #: editor/editor_file_dialog.cpp editor/editor_node.cpp #: editor/filesystem_dock.cpp editor/plugins/item_list_editor_plugin.cpp -#: editor/project_export.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_dock.cpp +#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp +#: editor/project_settings_editor.cpp editor/scene_tree_dock.cpp msgid "Delete" msgstr "" @@ -1120,7 +1112,7 @@ msgid "Add Bus" msgstr "" #: editor/editor_audio_buses.cpp -msgid "Create a new Bus Layout." +msgid "Add a new Audio Bus to this layout." msgstr "" #: editor/editor_audio_buses.cpp editor/editor_properties.cpp @@ -1149,6 +1141,10 @@ msgstr "" msgid "Load the default Bus Layout." msgstr "" +#: editor/editor_audio_buses.cpp +msgid "Create a new Bus Layout." +msgstr "" + #: editor/editor_autoload_settings.cpp msgid "Invalid name." msgstr "" @@ -2340,7 +2336,7 @@ msgid "Save & Restart" msgstr "" #: editor/editor_node.cpp -msgid "Spins when the editor window repaints!" +msgid "Spins when the editor window redraws." msgstr "" #: editor/editor_node.cpp @@ -3403,24 +3399,6 @@ msgid "Create Polygon" msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Edit Polygon" -msgstr "Ye be fixin' Signal:" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Insert Point" -msgstr "" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Edit Polygon (Remove Point)" -msgstr "" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Remove Polygon And Point" -msgstr "Discharge ye' Function" - -#: editor/plugins/abstract_polygon_2d_editor.cpp #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #, fuzzy @@ -3440,6 +3418,24 @@ msgstr "" msgid "Erase points." msgstr "Yar, Blow th' Selected Down!" +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Edit Polygon" +msgstr "Ye be fixin' Signal:" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Insert Point" +msgstr "" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Edit Polygon (Remove Point)" +msgstr "" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Remove Polygon And Point" +msgstr "Discharge ye' Function" + #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #: editor/plugins/animation_player_editor_plugin.cpp @@ -4230,6 +4226,16 @@ msgid "Move CanvasItem" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp +msgid "Presets for the anchors and margins values of a Control node." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp +msgid "" +"Children of containers have their anchors and margins values overridden by " +"their parent." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp msgid "Anchors only" msgstr "" @@ -5137,6 +5143,12 @@ msgid "Create UV Map" msgstr "" #: editor/plugins/polygon_2d_editor_plugin.cpp +msgid "" +"Polygon 2D has internal vertices, so it can no longer be edited in the " +"viewport." +msgstr "" + +#: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Create Polygon & UV" msgstr "" @@ -6243,7 +6255,7 @@ msgid "Post" msgstr "" #: editor/plugins/spatial_editor_plugin.cpp -msgid "Name-less gizmo" +msgid "Nameless gizmo" msgstr "" #: editor/plugins/sprite_editor_plugin.cpp @@ -6319,7 +6331,12 @@ msgid "(empty)" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animations" +#, fuzzy +msgid "Animations:" +msgstr "Yer functions:" + +#: editor/plugins/sprite_frames_editor_plugin.cpp +msgid "New Animation" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp @@ -6331,8 +6348,9 @@ msgid "Loop" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animation Frames" -msgstr "" +#, fuzzy +msgid "Animation Frames:" +msgstr "Yer unique name be evil." #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Insert Empty (Before)" @@ -7141,6 +7159,19 @@ msgstr "" #: editor/project_manager.cpp msgid "" +"The following project settings file does not specify the version of Godot " +"through which it was created.\n" +"\n" +"%s\n" +"\n" +"If you proceed with opening it, it will be converted to Godot's current " +"configuration file format.\n" +"Warning: You will not be able to open the project with previous versions of " +"the engine anymore." +msgstr "" + +#: editor/project_manager.cpp +msgid "" "The following project settings file was generated by an older engine " "version, and needs to be converted for this version:\n" "\n" @@ -8646,10 +8677,6 @@ msgid "Build Project" msgstr "" #: modules/mono/editor/mono_bottom_panel.cpp -msgid "Warnings" -msgstr "" - -#: modules/mono/editor/mono_bottom_panel.cpp msgid "View log" msgstr "" @@ -9310,6 +9337,13 @@ msgid "" "ParallaxLayer node only works when set as child of a ParallaxBackground node." msgstr "" +#: scene/2d/particles_2d.cpp +msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles2D node instead. You can use the \"Convert to " +"CPUParticles\" option for this purpose." +msgstr "" + #: scene/2d/particles_2d.cpp scene/3d/particles.cpp msgid "" "A material to process the particles is not assigned, so no behavior is " @@ -9465,6 +9499,13 @@ msgstr "" #: scene/3d/particles.cpp msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles node instead. You can use the \"Convert to CPUParticles" +"\" option for this purpose." +msgstr "" + +#: scene/3d/particles.cpp +msgid "" "Nothing is visible because meshes have not been assigned to draw passes." msgstr "" @@ -9495,21 +9536,6 @@ msgstr "" msgid "Path property must point to a valid Spatial node to work." msgstr "" -#: scene/3d/scenario_fx.cpp -msgid "WorldEnvironment needs an Environment resource." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " -"this environment's Background Mode to Canvas (for 2D scenes)." -msgstr "" - #: scene/3d/soft_body.cpp msgid "This body will be ignored until you set a mesh" msgstr "" @@ -9533,6 +9559,21 @@ msgid "" "it as a child of a VehicleBody." msgstr "" +#: scene/3d/world_environment.cpp +msgid "WorldEnvironment needs an Environment resource." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " +"this environment's Background Mode to Canvas (for 2D scenes)." +msgstr "" + #: scene/animation/animation_blend_tree.cpp msgid "On BlendTree node '%s', animation not found: '%s'" msgstr "" @@ -9575,11 +9616,19 @@ msgid "This node has been deprecated. Use AnimationTree instead." msgstr "" #: scene/gui/color_picker.cpp +msgid "Pick a color from the screen." +msgstr "" + +#: scene/gui/color_picker.cpp msgid "Raw Mode" msgstr "" #: scene/gui/color_picker.cpp -msgid "Add current color as a preset" +msgid "Switch between hexadecimal and code values." +msgstr "" + +#: scene/gui/color_picker.cpp +msgid "Add current color as a preset." msgstr "" #: scene/gui/dialogs.cpp diff --git a/editor/translations/pt_BR.po b/editor/translations/pt_BR.po index be32fed935..4282c467b8 100644 --- a/editor/translations/pt_BR.po +++ b/editor/translations/pt_BR.po @@ -34,7 +34,7 @@ # Bruno Miranda Da Silva <brunofreezee@gmail.com>, 2018. # Marcos Roberto Rodrigues Marques <contato.mroberto@gmail.com>, 2018. # Dyefferson Azevedo <gamecanalbrasil@gmail.com>, 2018. -# LucasSouza6 <lucasosouza66@gmail.com>, 2018. +# LucasSouza6 <lucasosouza66@gmail.com>, 2018, 2019. # Pedro Pacheco <pedroxixipa@hotmail.com>, 2018, 2019. # Bruno Henrique <nimbusdroid@gmail.com>, 2018, 2019. # Luciano Scilletta <lucianoscilletta@gmail.com>, 2018. @@ -48,12 +48,15 @@ # joel silva <joelgbsilva@gmail.com>, 2019. # Heitor Novais Pereira <heitornovais394@outlook.com>, 2019. # Joel Landgraf Filho <joel.landgraf@gmail.com>, 2019. +# Alan Valmorbida <alanvalmorbida@gmail.com>, 2019. +# João Vitor Ferreira Cavalcante <jvfecav@gmail.com>, 2019. +# Thiago Amendola <amendolathiago@gmail.com>, 2019. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: 2016-05-30\n" -"PO-Revision-Date: 2019-01-26 21:22+0000\n" -"Last-Translator: Eduardo Abreu <eduo.abreu@gmail.com>\n" +"PO-Revision-Date: 2019-02-14 02:10+0000\n" +"Last-Translator: Alan Valmorbida <alanvalmorbida@gmail.com>\n" "Language-Team: Portuguese (Brazil) <https://hosted.weblate.org/projects/" "godot-engine/godot/pt_BR/>\n" "Language: pt_BR\n" @@ -585,21 +588,14 @@ msgstr "Reduzir" msgid "Reset Zoom" msgstr "Redefinir Ampliação" -#: editor/code_editor.cpp -msgid "Warnings:" -msgstr "Avisos:" - -#: editor/code_editor.cpp -msgid "Font Size:" -msgstr "Tamanho da Fonte:" - -#: editor/code_editor.cpp -msgid "Line:" -msgstr "Linha:" +#: editor/code_editor.cpp modules/mono/editor/mono_bottom_panel.cpp +msgid "Warnings" +msgstr "Avisos" #: editor/code_editor.cpp -msgid "Col:" -msgstr "Coluna:" +#, fuzzy +msgid "Line and column numbers." +msgstr "Números de linha e coluna" #: editor/connections_dialog.cpp msgid "Method in target Node must be specified!" @@ -901,8 +897,8 @@ msgstr "Excluir arquivos selecionados?" #: editor/dependency_editor.cpp editor/editor_audio_buses.cpp #: editor/editor_file_dialog.cpp editor/editor_node.cpp #: editor/filesystem_dock.cpp editor/plugins/item_list_editor_plugin.cpp -#: editor/project_export.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_dock.cpp +#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp +#: editor/project_settings_editor.cpp editor/scene_tree_dock.cpp msgid "Delete" msgstr "Excluir" @@ -1158,8 +1154,9 @@ msgid "Add Bus" msgstr "Adicionar Canal" #: editor/editor_audio_buses.cpp -msgid "Create a new Bus Layout." -msgstr "Criar um novo Layout de Canais." +#, fuzzy +msgid "Add a new Audio Bus to this layout." +msgstr "Salvar Layout de Canais de Ãudio Como..." #: editor/editor_audio_buses.cpp editor/editor_properties.cpp #: editor/plugins/animation_player_editor_plugin.cpp editor/property_editor.cpp @@ -1187,6 +1184,10 @@ msgstr "Carregar Padrão" msgid "Load the default Bus Layout." msgstr "Carregar o Layout de Canais padrão." +#: editor/editor_audio_buses.cpp +msgid "Create a new Bus Layout." +msgstr "Criar um novo Layout de Canais." + #: editor/editor_autoload_settings.cpp msgid "Invalid name." msgstr "Nome Inválido." @@ -2433,7 +2434,8 @@ msgid "Save & Restart" msgstr "Salvar e Reiniciar" #: editor/editor_node.cpp -msgid "Spins when the editor window repaints!" +#, fuzzy +msgid "Spins when the editor window redraws." msgstr "Gira quando a janela do editor atualiza!" #: editor/editor_node.cpp @@ -3359,17 +3361,19 @@ msgstr "Reimportar" #: editor/import_dock.cpp msgid "Save scenes, re-import and restart" -msgstr "" +msgstr "Salvar cenas, reimportar e reiniciar" #: editor/import_dock.cpp -#, fuzzy msgid "Changing the type of an imported file requires editor restart." -msgstr "Mudar o driver de vÃdeo necessita reinicializar o editor." +msgstr "" +"Mudar o tipo de um arquivo importado necessita a reinicialização do editor." #: editor/import_dock.cpp msgid "" "WARNING: Assets exist that use this resource, they may stop loading properly." msgstr "" +"AVISO: Existem objetos que utilizam esse recurso, eles podem parar de " +"carregar apropriadamente." #: editor/inspector_dock.cpp msgid "Failed to load resource." @@ -3494,22 +3498,6 @@ msgid "Create Polygon" msgstr "Criar PolÃgono" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Edit Polygon" -msgstr "Editar PolÃgono" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Insert Point" -msgstr "Inserir Ponto" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Edit Polygon (Remove Point)" -msgstr "Editar PolÃgono (Remover Ponto)" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Remove Polygon And Point" -msgstr "Remover PolÃgono e Ponto" - -#: editor/plugins/abstract_polygon_2d_editor.cpp #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp msgid "Create points." @@ -3530,6 +3518,22 @@ msgstr "" msgid "Erase points." msgstr "Apagar pontos." +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Edit Polygon" +msgstr "Editar PolÃgono" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Insert Point" +msgstr "Inserir Ponto" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Edit Polygon (Remove Point)" +msgstr "Editar PolÃgono (Remover Ponto)" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Remove Polygon And Point" +msgstr "Remover PolÃgono e Ponto" + #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #: editor/plugins/animation_player_editor_plugin.cpp @@ -3572,7 +3576,7 @@ msgstr "Definir posição de mescla dentro do espaço" #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp msgid "Select and move points, create points with RMB." -msgstr "Selecione e mova pontos, crie pontos com o Botão Direito do Mouse." +msgstr "Selecionar e mover pontos, criar pontos com o botão direito do mouse." #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp scene/gui/graph_edit.cpp @@ -4336,6 +4340,19 @@ msgid "Move CanvasItem" msgstr "Mover CanvaItem" #: editor/plugins/canvas_item_editor_plugin.cpp +msgid "Presets for the anchors and margins values of a Control node." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp +#, fuzzy +msgid "" +"Children of containers have their anchors and margins values overridden by " +"their parent." +msgstr "" +"Filhos de contêineres tem suas posições e tamanhos sobrescritos pelos seus " +"pais." + +#: editor/plugins/canvas_item_editor_plugin.cpp msgid "Anchors only" msgstr "Apenas âncoras" @@ -5244,6 +5261,12 @@ msgid "Create UV Map" msgstr "Criar Mapa UV" #: editor/plugins/polygon_2d_editor_plugin.cpp +msgid "" +"Polygon 2D has internal vertices, so it can no longer be edited in the " +"viewport." +msgstr "" + +#: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Create Polygon & UV" msgstr "Criar PolÃgono & UV" @@ -6334,7 +6357,8 @@ msgid "Post" msgstr "Pós" #: editor/plugins/spatial_editor_plugin.cpp -msgid "Name-less gizmo" +#, fuzzy +msgid "Nameless gizmo" msgstr "Gaveta sem nome" #: editor/plugins/sprite_editor_plugin.cpp @@ -6411,8 +6435,12 @@ msgid "(empty)" msgstr "(vazio)" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animations" -msgstr "Animações" +msgid "Animations:" +msgstr "Animações:" + +#: editor/plugins/sprite_frames_editor_plugin.cpp +msgid "New Animation" +msgstr "Nova animação" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed (FPS):" @@ -6423,8 +6451,8 @@ msgid "Loop" msgstr "Repetir" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animation Frames" -msgstr "Quadros da Animação" +msgid "Animation Frames:" +msgstr "Quadros da Animação:" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Insert Empty (Before)" @@ -6909,7 +6937,7 @@ msgstr "Fragmento" #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Light" -msgstr "Leve" +msgstr "Luz" #: editor/plugins/visual_shader_editor_plugin.cpp msgid "VisualShader" @@ -7178,11 +7206,11 @@ msgstr "Navegar" #: editor/project_manager.cpp msgid "Renderer:" -msgstr "" +msgstr "Renderizador:" #: editor/project_manager.cpp msgid "OpenGL ES 3.0" -msgstr "" +msgstr "OpenGL ES 3.0" #: editor/project_manager.cpp msgid "" @@ -7191,10 +7219,14 @@ msgid "" "Incompatible with older hardware\n" "Not recommended for web games" msgstr "" +"Maior qualidade visual\n" +"Todas as funções disponÃveis\n" +"IncompatÃvel com hardware antigo\n" +"Não recomendado para jogos web" #: editor/project_manager.cpp msgid "OpenGL ES 2.0" -msgstr "" +msgstr "OpenGL ES 2.0" #: editor/project_manager.cpp msgid "" @@ -7203,10 +7235,16 @@ msgid "" "Works on most hardware\n" "Recommended for web games" msgstr "" +"Menor qualidade visual\n" +"Algumas funções não disponÃveis\n" +"Funciona na maioria dos hardwares\n" +"Recomendado para jogos web" #: editor/project_manager.cpp msgid "Renderer can be changed later, but scenes may need to be adjusted." msgstr "" +"Renderizador pode ser alterado posteriormente, porém, cenas poderão " +"necessitar de ajustes." #: editor/project_manager.cpp msgid "Unnamed Project" @@ -7221,6 +7259,28 @@ msgid "Are you sure to open more than one project?" msgstr "Tem certeza de que quer abrir mais de um projeto?" #: editor/project_manager.cpp +#, fuzzy +msgid "" +"The following project settings file does not specify the version of Godot " +"through which it was created.\n" +"\n" +"%s\n" +"\n" +"If you proceed with opening it, it will be converted to Godot's current " +"configuration file format.\n" +"Warning: You will not be able to open the project with previous versions of " +"the engine anymore." +msgstr "" +"O seguinte arquivo de configurações do projeto foi gerado por uma versão " +"mais antiga do mecanismo e precisa ser convertido para esta versão:\n" +"\n" +"%s\n" +"\n" +"Você deseja realizar a conversão?\n" +"Aviso: você não poderá mais abrir o projeto com versões anteriores do " +"mecanismo." + +#: editor/project_manager.cpp msgid "" "The following project settings file was generated by an older engine " "version, and needs to be converted for this version:\n" @@ -7932,11 +7992,13 @@ msgid "Duplicate Node(s)" msgstr "Duplicar Nó(s)" #: editor/scene_tree_dock.cpp +#, fuzzy msgid "Can't reparent nodes in inherited scenes, order of nodes can't change." msgstr "" +"Não é possÃvel re-hierarquizar nós em cenas herdadas, a ordem dos nós não " +"pode ser alterada." #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Node must belong to the edited scene to become root." msgstr "Node necessita pertencer à cena editada para se tornar raiz." @@ -8751,10 +8813,6 @@ msgid "Build Project" msgstr "Compilar Projeto" #: modules/mono/editor/mono_bottom_panel.cpp -msgid "Warnings" -msgstr "Avisos" - -#: modules/mono/editor/mono_bottom_panel.cpp msgid "View log" msgstr "Ver registro" @@ -9157,12 +9215,10 @@ msgid "Set %s" msgstr "Conjunto %s" #: platform/android/export/export.cpp -#, fuzzy msgid "Package name is missing." msgstr "Nome do pacote está faltando." #: platform/android/export/export.cpp -#, fuzzy msgid "Package segments must be of non-zero length." msgstr "Seguimentos de pacote necessitam ser de tamanho diferente de zero." @@ -9179,70 +9235,75 @@ msgstr "" #: platform/android/export/export.cpp msgid "The character '%s' cannot be the first character in a package segment." msgstr "" +"O caractere '%s' não pode ser o primeiro caractere em um segmento de pacote." #: platform/android/export/export.cpp msgid "The package must have at least one '.' separator." -msgstr "" +msgstr "O pacote deve ter pelo menos um separador '.'." #: platform/android/export/export.cpp msgid "ADB executable not configured in the Editor Settings." -msgstr "" +msgstr "Executável ADB não configurado nas opções do Editor." #: platform/android/export/export.cpp msgid "OpenJDK jarsigner not configured in the Editor Settings." -msgstr "" +msgstr "OpenJDK jarsigner não configurado nas opções do Editor." #: platform/android/export/export.cpp msgid "Debug keystore not configured in the Editor Settings nor in the preset." msgstr "" #: platform/android/export/export.cpp +#, fuzzy msgid "Invalid public key for APK expansion." -msgstr "" +msgstr "Chave pública inválida para expansão de APK." #: platform/android/export/export.cpp -#, fuzzy msgid "Invalid package name:" -msgstr "Nome de classe inválido" +msgstr "Nome de pacote inválido:" #: platform/iphone/export/export.cpp msgid "Identifier is missing." -msgstr "" +msgstr "Identificador está ausente." #: platform/iphone/export/export.cpp +#, fuzzy msgid "Identifier segments must be of non-zero length." -msgstr "" +msgstr "O identificador deve ter comprimento diferente de zero." #: platform/iphone/export/export.cpp -#, fuzzy msgid "The character '%s' is not allowed in Identifier." -msgstr "O nome não é um identificador valido:" +msgstr "O caractere '%s' não é permitido no identificador." #: platform/iphone/export/export.cpp msgid "A digit cannot be the first character in a Identifier segment." msgstr "" +"Um digito não pode ser o primeiro caractere de um segmento identificador." #: platform/iphone/export/export.cpp msgid "" "The character '%s' cannot be the first character in a Identifier segment." msgstr "" +"O caractere '%s' não pode ser o primeiro caractere de um segmento " +"identificador." #: platform/iphone/export/export.cpp msgid "The Identifier must have at least one '.' separator." -msgstr "" +msgstr "O identificador deve ter pelo menos um separador '.'." #: platform/iphone/export/export.cpp msgid "App Store Team ID not specified - cannot configure the project." msgstr "" +"App Store Team ID não especificado - não é possÃvel configurar o projeto." #: platform/iphone/export/export.cpp -#, fuzzy msgid "Invalid Identifier:" -msgstr "O nome não é um identificador valido:" +msgstr "O nome não é um identificador válido:" #: platform/iphone/export/export.cpp +#, fuzzy msgid "Required icon is not specified in the preset." -msgstr "" +msgstr "Ãcone necessário não especificado na predefinição." #: platform/javascript/export/export.cpp msgid "Run in Browser" @@ -9277,43 +9338,46 @@ msgid "Using default boot splash image." msgstr "Usando imagem boot splash padrão." #: platform/uwp/export/export.cpp -#, fuzzy msgid "Invalid package unique name." -msgstr "Nome único inválido." +msgstr "Nome único de pacote inválido." #: platform/uwp/export/export.cpp -#, fuzzy msgid "Invalid product GUID." -msgstr "Tamanho de fonte inválido." +msgstr "GUID de produto inválido." #: platform/uwp/export/export.cpp #, fuzzy msgid "Invalid publisher GUID." -msgstr "Caminho base inválido" +msgstr "GUID do editor inválido." #: platform/uwp/export/export.cpp msgid "Invalid background color." msgstr "Cor de fundo inválida." #: platform/uwp/export/export.cpp +#, fuzzy msgid "Invalid Store Logo image dimensions (should be 50x50)." -msgstr "" +msgstr "Dimensões inválidas do logo da loja (deve ser 50x50)." #: platform/uwp/export/export.cpp +#, fuzzy msgid "Invalid square 44x44 logo image dimensions (should be 44x44)." -msgstr "" +msgstr "Dimensões inválidas do logo quadrado de 44x44 (deve ser 44x44)." #: platform/uwp/export/export.cpp +#, fuzzy msgid "Invalid square 71x71 logo image dimensions (should be 71x71)." -msgstr "" +msgstr "Dimensões inválidas do logo quadrado de 71x71 (deve ser 71x71)." #: platform/uwp/export/export.cpp +#, fuzzy msgid "Invalid square 150x150 logo image dimensions (should be 150x150)." -msgstr "" +msgstr "Dimensões inválidas do logo quadrado de 150x150 (deve ser 150x150)." #: platform/uwp/export/export.cpp +#, fuzzy msgid "Invalid square 310x310 logo image dimensions (should be 310x310)." -msgstr "" +msgstr "Dimensões inválidas do logo quadrado de 310x310 (deve ser 310x310)." #: platform/uwp/export/export.cpp msgid "Invalid wide 310x150 logo image dimensions (should be 310x150)." @@ -9433,6 +9497,13 @@ msgstr "" "O nó ParallaxLayer apenas funciona quando definido como filho de um nó " "ParallaxBackground." +#: scene/2d/particles_2d.cpp +msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles2D node instead. You can use the \"Convert to " +"CPUParticles\" option for this purpose." +msgstr "" + #: scene/2d/particles_2d.cpp scene/3d/particles.cpp msgid "" "A material to process the particles is not assigned, so no behavior is " @@ -9624,6 +9695,13 @@ msgstr "" #: scene/3d/particles.cpp msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles node instead. You can use the \"Convert to CPUParticles" +"\" option for this purpose." +msgstr "" + +#: scene/3d/particles.cpp +msgid "" "Nothing is visible because meshes have not been assigned to draw passes." msgstr "" "Nada está visÃvel porque as meshes não foram atribuÃdas a passes de desenho." @@ -9663,25 +9741,6 @@ msgstr "" msgid "Path property must point to a valid Spatial node to work." msgstr "A propriedade Caminho deve apontar para um nó Spatial para funcionar." -#: scene/3d/scenario_fx.cpp -msgid "WorldEnvironment needs an Environment resource." -msgstr "WorldEnvironment precisa de um recurso Environment." - -#: scene/3d/scenario_fx.cpp -msgid "" -"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." -msgstr "" -"É permitido apenas um nó WorldEnvironment por cena (ou conjunto de cenas " -"instanciadas)." - -#: scene/3d/scenario_fx.cpp -msgid "" -"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " -"this environment's Background Mode to Canvas (for 2D scenes)." -msgstr "" -"Este WorldEnvironment está sendo ignorado. Adicione uma Camera (para cenas " -"3D) ou defina o Background Mode deste ambiente para Canvas (para cenas 2D)." - #: scene/3d/soft_body.cpp msgid "This body will be ignored until you set a mesh" msgstr "Este corpo será ignorado até você definir uma malha" @@ -9712,6 +9771,25 @@ msgstr "" "VehiceWheel serve para fornecer um sistema de rodas para um VehicleBody. Por " "favor, use ele como um filho de um VehicleBody." +#: scene/3d/world_environment.cpp +msgid "WorldEnvironment needs an Environment resource." +msgstr "WorldEnvironment precisa de um recurso Environment." + +#: scene/3d/world_environment.cpp +msgid "" +"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." +msgstr "" +"É permitido apenas um nó WorldEnvironment por cena (ou conjunto de cenas " +"instanciadas)." + +#: scene/3d/world_environment.cpp +msgid "" +"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " +"this environment's Background Mode to Canvas (for 2D scenes)." +msgstr "" +"Este WorldEnvironment está sendo ignorado. Adicione uma Camera (para cenas " +"3D) ou defina o Background Mode deste ambiente para Canvas (para cenas 2D)." + #: scene/animation/animation_blend_tree.cpp msgid "On BlendTree node '%s', animation not found: '%s'" msgstr "No nó do BlendTree '%s', animação não encontrada: '%s'" @@ -9756,11 +9834,20 @@ msgid "This node has been deprecated. Use AnimationTree instead." msgstr "Este nó foi reprovado. Use AnimationTree em vez disso." #: scene/gui/color_picker.cpp +msgid "Pick a color from the screen." +msgstr "" + +#: scene/gui/color_picker.cpp msgid "Raw Mode" msgstr "Modo Bruto" #: scene/gui/color_picker.cpp -msgid "Add current color as a preset" +msgid "Switch between hexadecimal and code values." +msgstr "" + +#: scene/gui/color_picker.cpp +#, fuzzy +msgid "Add current color as a preset." msgstr "Adicionar cor atual como uma predefinição" #: scene/gui/dialogs.cpp @@ -9855,6 +9942,18 @@ msgstr "Atribuição à uniforme." msgid "Varyings can only be assigned in vertex function." msgstr "Variáveis só podem ser atribuÃdas na função de vértice." +#~ msgid "Warnings:" +#~ msgstr "Avisos:" + +#~ msgid "Font Size:" +#~ msgstr "Tamanho da Fonte:" + +#~ msgid "Line:" +#~ msgstr "Linha:" + +#~ msgid "Col:" +#~ msgstr "Coluna:" + #~ msgid "OrientedPathFollow only works when set as a child of a Path node." #~ msgstr "" #~ "OrientedPathFollow só funciona quando definido como filho de um nó Path." diff --git a/editor/translations/pt_PT.po b/editor/translations/pt_PT.po index c3e9b189c2..ef090612ca 100644 --- a/editor/translations/pt_PT.po +++ b/editor/translations/pt_PT.po @@ -18,8 +18,8 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2019-01-26 21:22+0000\n" -"Last-Translator: ssantos <ssantos@web.de>\n" +"PO-Revision-Date: 2019-02-01 12:09+0000\n" +"Last-Translator: João Lopes <linux-man@hotmail.com>\n" "Language-Team: Portuguese (Portugal) <https://hosted.weblate.org/projects/" "godot-engine/godot/pt_PT/>\n" "Language: pt_PT\n" @@ -554,21 +554,13 @@ msgstr "Zoom Out" msgid "Reset Zoom" msgstr "Repor Zoom" -#: editor/code_editor.cpp -msgid "Warnings:" -msgstr "Avisos:" - -#: editor/code_editor.cpp -msgid "Font Size:" -msgstr "Tamanho do tipo de letra:" - -#: editor/code_editor.cpp -msgid "Line:" -msgstr "Linha:" +#: editor/code_editor.cpp modules/mono/editor/mono_bottom_panel.cpp +msgid "Warnings" +msgstr "Avisos" #: editor/code_editor.cpp -msgid "Col:" -msgstr "Coluna:" +msgid "Line and column numbers." +msgstr "" #: editor/connections_dialog.cpp msgid "Method in target Node must be specified!" @@ -870,8 +862,8 @@ msgstr "Apagar arquivos selecionados?" #: editor/dependency_editor.cpp editor/editor_audio_buses.cpp #: editor/editor_file_dialog.cpp editor/editor_node.cpp #: editor/filesystem_dock.cpp editor/plugins/item_list_editor_plugin.cpp -#: editor/project_export.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_dock.cpp +#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp +#: editor/project_settings_editor.cpp editor/scene_tree_dock.cpp msgid "Delete" msgstr "Apagar" @@ -1127,8 +1119,9 @@ msgid "Add Bus" msgstr "Adicionar Barramento" #: editor/editor_audio_buses.cpp -msgid "Create a new Bus Layout." -msgstr "Criar um novo Modelo de Barramento." +#, fuzzy +msgid "Add a new Audio Bus to this layout." +msgstr "Guardar Modelo do barramento de áudio como..." #: editor/editor_audio_buses.cpp editor/editor_properties.cpp #: editor/plugins/animation_player_editor_plugin.cpp editor/property_editor.cpp @@ -1156,6 +1149,10 @@ msgstr "Carregar Padrão" msgid "Load the default Bus Layout." msgstr "Carregar o Modelo padrão de barramento." +#: editor/editor_audio_buses.cpp +msgid "Create a new Bus Layout." +msgstr "Criar um novo Modelo de Barramento." + #: editor/editor_autoload_settings.cpp msgid "Invalid name." msgstr "Nome inválido." @@ -2403,7 +2400,8 @@ msgid "Save & Restart" msgstr "Guardar & Reiniciar" #: editor/editor_node.cpp -msgid "Spins when the editor window repaints!" +#, fuzzy +msgid "Spins when the editor window redraws." msgstr "Roda quando a janela do Editor atualiza!" #: editor/editor_node.cpp @@ -3327,17 +3325,18 @@ msgstr "Reimportar" #: editor/import_dock.cpp msgid "Save scenes, re-import and restart" -msgstr "" +msgstr "Guardar cenas, reimportar e reiniciar" #: editor/import_dock.cpp -#, fuzzy msgid "Changing the type of an imported file requires editor restart." -msgstr "Alterar o driver de vÃdeo requer reiniciar o editor." +msgstr "Alterar o tipo de um ficheiro importado requer reiniciar o editor." #: editor/import_dock.cpp msgid "" "WARNING: Assets exist that use this resource, they may stop loading properly." msgstr "" +"AVISO: Existem Ativos que usam este recurso, podendo não ser carregados " +"corretamente." #: editor/inspector_dock.cpp msgid "Failed to load resource." @@ -3462,22 +3461,6 @@ msgid "Create Polygon" msgstr "Criar PolÃgono" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Edit Polygon" -msgstr "Editar PolÃgono" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Insert Point" -msgstr "Inserir Ponto" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Edit Polygon (Remove Point)" -msgstr "Editar PolÃgono (Remover Ponto)" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Remove Polygon And Point" -msgstr "Remover PolÃgono e Ponto" - -#: editor/plugins/abstract_polygon_2d_editor.cpp #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp msgid "Create points." @@ -3498,6 +3481,22 @@ msgstr "" msgid "Erase points." msgstr "Apagar pontos." +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Edit Polygon" +msgstr "Editar PolÃgono" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Insert Point" +msgstr "Inserir Ponto" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Edit Polygon (Remove Point)" +msgstr "Editar PolÃgono (Remover Ponto)" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Remove Polygon And Point" +msgstr "Remover PolÃgono e Ponto" + #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #: editor/plugins/animation_player_editor_plugin.cpp @@ -4297,6 +4296,19 @@ msgid "Move CanvasItem" msgstr "Mover CanvasItem" #: editor/plugins/canvas_item_editor_plugin.cpp +msgid "Presets for the anchors and margins values of a Control node." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp +#, fuzzy +msgid "" +"Children of containers have their anchors and margins values overridden by " +"their parent." +msgstr "" +"Atenção: as crianças de um contentor obtêm a sua posição e tamanho " +"determinados apenas pelos seus pais." + +#: editor/plugins/canvas_item_editor_plugin.cpp msgid "Anchors only" msgstr "Só âncoras" @@ -5201,6 +5213,12 @@ msgid "Create UV Map" msgstr "Criar mapa UV" #: editor/plugins/polygon_2d_editor_plugin.cpp +msgid "" +"Polygon 2D has internal vertices, so it can no longer be edited in the " +"viewport." +msgstr "" + +#: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Create Polygon & UV" msgstr "Criar PolÃgono & UV" @@ -6291,7 +6309,8 @@ msgid "Post" msgstr "Pós" #: editor/plugins/spatial_editor_plugin.cpp -msgid "Name-less gizmo" +#, fuzzy +msgid "Nameless gizmo" msgstr "Bugiganga sem nome" #: editor/plugins/sprite_editor_plugin.cpp @@ -6367,10 +6386,16 @@ msgid "(empty)" msgstr "(vazio)" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animations" +#, fuzzy +msgid "Animations:" msgstr "Animações" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "New Animation" +msgstr "Animação" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed (FPS):" msgstr "Velocidade (FPS):" @@ -6379,7 +6404,8 @@ msgid "Loop" msgstr "Ciclo" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animation Frames" +#, fuzzy +msgid "Animation Frames:" msgstr "Frames da Animação" #: editor/plugins/sprite_frames_editor_plugin.cpp @@ -7134,11 +7160,11 @@ msgstr "Navegar" #: editor/project_manager.cpp msgid "Renderer:" -msgstr "" +msgstr "Renderizador:" #: editor/project_manager.cpp msgid "OpenGL ES 3.0" -msgstr "" +msgstr "OpenGL ES 3.0" #: editor/project_manager.cpp msgid "" @@ -7147,10 +7173,14 @@ msgid "" "Incompatible with older hardware\n" "Not recommended for web games" msgstr "" +"Qualidade visual superior\n" +"Todas as caracterÃsticas disponÃveis\n" +"IncompatÃvel com hardware antigo\n" +"Não recomendado para jogos Web" #: editor/project_manager.cpp msgid "OpenGL ES 2.0" -msgstr "" +msgstr "OpenGL ES 2.0" #: editor/project_manager.cpp msgid "" @@ -7159,10 +7189,16 @@ msgid "" "Works on most hardware\n" "Recommended for web games" msgstr "" +"Qualidade visual inferior\n" +"Algumas caracterÃsticas indisponÃveis\n" +"Funciona na maioria do hardware\n" +"Recomendado para jogos Web" #: editor/project_manager.cpp msgid "Renderer can be changed later, but scenes may need to be adjusted." msgstr "" +"O Renderizador pode ser alterado mais tarde, mas as cenas poderão ter de ser " +"ajustadas." #: editor/project_manager.cpp msgid "Unnamed Project" @@ -7177,6 +7213,28 @@ msgid "Are you sure to open more than one project?" msgstr "Está seguro que quer abrir mais do que um Projeto?" #: editor/project_manager.cpp +#, fuzzy +msgid "" +"The following project settings file does not specify the version of Godot " +"through which it was created.\n" +"\n" +"%s\n" +"\n" +"If you proceed with opening it, it will be converted to Godot's current " +"configuration file format.\n" +"Warning: You will not be able to open the project with previous versions of " +"the engine anymore." +msgstr "" +"A seguinte configuração do projeto foi gerada por um motor mais antigo, e " +"precisa de ser convertida para esta versão.\n" +"\n" +"%s\n" +"\n" +"Deseja convertê-la?\n" +"Aviso: Não conseguirá mais abrir o projeto em versões anteriores à deste " +"motor." + +#: editor/project_manager.cpp msgid "" "The following project settings file was generated by an older engine " "version, and needs to be converted for this version:\n" @@ -7888,7 +7946,7 @@ msgstr "Duplicar Nó(s)" #: editor/scene_tree_dock.cpp msgid "Can't reparent nodes in inherited scenes, order of nodes can't change." -msgstr "" +msgstr "ImpossÃvel mudar nó em cenas herdadas, a ordem dos nós não pode mudar." #: editor/scene_tree_dock.cpp msgid "Node must belong to the edited scene to become root." @@ -8705,10 +8763,6 @@ msgid "Build Project" msgstr "Construir Projeto" #: modules/mono/editor/mono_bottom_panel.cpp -msgid "Warnings" -msgstr "Avisos" - -#: modules/mono/editor/mono_bottom_panel.cpp msgid "View log" msgstr "Ver log" @@ -9119,16 +9173,15 @@ msgstr "Os segmentos de pacote devem ser de comprimento diferente de zero." #: platform/android/export/export.cpp msgid "The character '%s' is not allowed in Android application package names." msgstr "" -"O caractere '%s' não é permitido em nomes de pacotes de aplicativos Android." +"O caráter '%s' não é permitido em nomes de pacotes de aplicações Android." #: platform/android/export/export.cpp msgid "A digit cannot be the first character in a package segment." -msgstr "Um dÃgito não pode ser o primeiro caractere num segmento de pacote." +msgstr "Um dÃgito não pode ser o primeiro caráter num segmento de pacote." #: platform/android/export/export.cpp msgid "The character '%s' cannot be the first character in a package segment." -msgstr "" -"O caractere '%s' não pode ser o primeiro caractere num segmento de pacote." +msgstr "O caráter '%s' não pode ser o primeiro caráter num segmento de pacote." #: platform/android/export/export.cpp msgid "The package must have at least one '.' separator." @@ -9166,18 +9219,18 @@ msgstr "Identificador de segmentos devem ser de comprimento diferente de zero." #: platform/iphone/export/export.cpp msgid "The character '%s' is not allowed in Identifier." -msgstr "O caractere \"%s\" não é permitido no Identificador." +msgstr "O caráter \"%s\" não é permitido no Identificador." #: platform/iphone/export/export.cpp msgid "A digit cannot be the first character in a Identifier segment." msgstr "" -"Um dÃgito não pode ser o primeiro caractere em um segmento de Identificador." +"Um dÃgito não pode ser o primeiro caráter num segmento de Identificador." #: platform/iphone/export/export.cpp msgid "" "The character '%s' cannot be the first character in a Identifier segment." msgstr "" -"O caractere \"%s\" não pode ser o primeiro caractere num segmento de " +"O caráter \"%s\" não pode ser o primeiro caráter num segmento de " "Identificador." #: platform/iphone/export/export.cpp @@ -9390,6 +9443,13 @@ msgstr "" "O Nó ParallaxLayer só funciona quando definido como filho de um Nó " "ParallaxBackground." +#: scene/2d/particles_2d.cpp +msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles2D node instead. You can use the \"Convert to " +"CPUParticles\" option for this purpose." +msgstr "" + #: scene/2d/particles_2d.cpp scene/3d/particles.cpp msgid "" "A material to process the particles is not assigned, so no behavior is " @@ -9579,6 +9639,13 @@ msgstr "" #: scene/3d/particles.cpp msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles node instead. You can use the \"Convert to CPUParticles" +"\" option for this purpose." +msgstr "" + +#: scene/3d/particles.cpp +msgid "" "Nothing is visible because meshes have not been assigned to draw passes." msgstr "" "Nada é visÃvel porque não foram atribuÃdas Meshes aos passos de desenho." @@ -9600,8 +9667,8 @@ msgid "" "PathFollow ROTATION_ORIENTED requires \"Up Vector\" enabled in its parent " "Path's Curve resource." msgstr "" -"PathFollow ROTATION_ORIENTED requer \"Up Vector\" habilitado em seu recurso " -"de Curva do caminho pai." +"PathFollow ROTATION_ORIENTED requer \"Up Vector\" habilitado no recurso de " +"Curva do Caminho do seu pai." #: scene/3d/physics_body.cpp msgid "" @@ -9619,25 +9686,6 @@ msgstr "" "Para funcionar, a Propriedade Caminho tem de apontar para um Nó Spatial " "válido." -#: scene/3d/scenario_fx.cpp -msgid "WorldEnvironment needs an Environment resource." -msgstr "WorldEnvironment precisa de um recurso Environment." - -#: scene/3d/scenario_fx.cpp -msgid "" -"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." -msgstr "" -"Apenas um WorldEnvironment é permitido por Cena (ou grupo de cenas " -"instanciadas)." - -#: scene/3d/scenario_fx.cpp -msgid "" -"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " -"this environment's Background Mode to Canvas (for 2D scenes)." -msgstr "" -"Este WorldEnvironment Ä— ignorado. Pode adicionar uma Camera (para cenas 3D) " -"ou definir o Modo Background deste ambiente como Canvas (para cenas 2D)." - #: scene/3d/soft_body.cpp msgid "This body will be ignored until you set a mesh" msgstr "Este corpo será ignorado até se definir uma Malha" @@ -9668,6 +9716,25 @@ msgstr "" "VehicleWheel fornece um sistema de rodas a um VehicleBody. Use-o como um " "filho de VehicleBody." +#: scene/3d/world_environment.cpp +msgid "WorldEnvironment needs an Environment resource." +msgstr "WorldEnvironment precisa de um recurso Environment." + +#: scene/3d/world_environment.cpp +msgid "" +"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." +msgstr "" +"Apenas um WorldEnvironment é permitido por Cena (ou grupo de cenas " +"instanciadas)." + +#: scene/3d/world_environment.cpp +msgid "" +"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " +"this environment's Background Mode to Canvas (for 2D scenes)." +msgstr "" +"Este WorldEnvironment Ä— ignorado. Pode adicionar uma Camera (para cenas 3D) " +"ou definir o Modo Background deste ambiente como Canvas (para cenas 2D)." + #: scene/animation/animation_blend_tree.cpp msgid "On BlendTree node '%s', animation not found: '%s'" msgstr "No nó BlendTree '%s', animação não encontrada: '%s'" @@ -9711,11 +9778,20 @@ msgid "This node has been deprecated. Use AnimationTree instead." msgstr "Este nó foi depreciado. Use AnimationTree em vez disso." #: scene/gui/color_picker.cpp +msgid "Pick a color from the screen." +msgstr "" + +#: scene/gui/color_picker.cpp msgid "Raw Mode" msgstr "Modo Raw" #: scene/gui/color_picker.cpp -msgid "Add current color as a preset" +msgid "Switch between hexadecimal and code values." +msgstr "" + +#: scene/gui/color_picker.cpp +#, fuzzy +msgid "Add current color as a preset." msgstr "Adicionar cor atual como predefinição" #: scene/gui/dialogs.cpp @@ -9810,6 +9886,18 @@ msgstr "Atribuição a uniforme." msgid "Varyings can only be assigned in vertex function." msgstr "Variações só podem ser atribuÃdas na função vértice." +#~ msgid "Warnings:" +#~ msgstr "Avisos:" + +#~ msgid "Font Size:" +#~ msgstr "Tamanho do tipo de letra:" + +#~ msgid "Line:" +#~ msgstr "Linha:" + +#~ msgid "Col:" +#~ msgstr "Coluna:" + #~ msgid "OrientedPathFollow only works when set as a child of a Path node." #~ msgstr "" #~ "OrientedPathFollow apenas funciona quando definido como filho de um Nó " diff --git a/editor/translations/ro.po b/editor/translations/ro.po index 88e95546a6..c19c594ac6 100644 --- a/editor/translations/ro.po +++ b/editor/translations/ro.po @@ -558,22 +558,13 @@ msgstr "Zoom-aÈ›i Afară" msgid "Reset Zoom" msgstr "ResetaÈ›i Zoom-area" -#: editor/code_editor.cpp -msgid "Warnings:" +#: editor/code_editor.cpp modules/mono/editor/mono_bottom_panel.cpp +msgid "Warnings" msgstr "" #: editor/code_editor.cpp -#, fuzzy -msgid "Font Size:" -msgstr "Dimensiunea Conturului:" - -#: editor/code_editor.cpp -msgid "Line:" -msgstr "Linie:" - -#: editor/code_editor.cpp -msgid "Col:" -msgstr "Col:" +msgid "Line and column numbers." +msgstr "" #: editor/connections_dialog.cpp msgid "Method in target Node must be specified!" @@ -883,8 +874,8 @@ msgstr "ÅžtergeÈ›i fiÅŸierele selectate?" #: editor/dependency_editor.cpp editor/editor_audio_buses.cpp #: editor/editor_file_dialog.cpp editor/editor_node.cpp #: editor/filesystem_dock.cpp editor/plugins/item_list_editor_plugin.cpp -#: editor/project_export.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_dock.cpp +#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp +#: editor/project_settings_editor.cpp editor/scene_tree_dock.cpp msgid "Delete" msgstr "ȘtergeÈ›i" @@ -1141,8 +1132,9 @@ msgid "Add Bus" msgstr "AdaugaÈ›i Pistă Audio" #: editor/editor_audio_buses.cpp -msgid "Create a new Bus Layout." -msgstr "CreaÅ£i o Schemă nouă de Pistă Audio." +#, fuzzy +msgid "Add a new Audio Bus to this layout." +msgstr "SalvaÈ›i Schema Pistei Audio Ca..." #: editor/editor_audio_buses.cpp editor/editor_properties.cpp #: editor/plugins/animation_player_editor_plugin.cpp editor/property_editor.cpp @@ -1170,6 +1162,10 @@ msgstr "ÃŽncărcaÈ›i Implicit" msgid "Load the default Bus Layout." msgstr "ÃŽncarcă Schema de Pistă Audio implicită." +#: editor/editor_audio_buses.cpp +msgid "Create a new Bus Layout." +msgstr "CreaÅ£i o Schemă nouă de Pistă Audio." + #: editor/editor_autoload_settings.cpp msgid "Invalid name." msgstr "Nume nevalid." @@ -2446,7 +2442,8 @@ msgid "Save & Restart" msgstr "Salvează È™i Restartează" #: editor/editor_node.cpp -msgid "Spins when the editor window repaints!" +#, fuzzy +msgid "Spins when the editor window redraws." msgstr "Se roteÈ™te când ferestra editorului se recolorează!" #: editor/editor_node.cpp @@ -3542,25 +3539,6 @@ msgid "Create Polygon" msgstr "Crează Poligon" #: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Edit Polygon" -msgstr "Editează Poligon" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Insert Point" -msgstr "Inserează Punct" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Edit Polygon (Remove Point)" -msgstr "Editează Poligon (Elimină Punct)" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Remove Polygon And Point" -msgstr "Elimină Poligon Și Punct" - -#: editor/plugins/abstract_polygon_2d_editor.cpp #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #, fuzzy @@ -3585,6 +3563,25 @@ msgstr "" msgid "Erase points." msgstr "RMB: Șterge Punctul." +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Edit Polygon" +msgstr "Editează Poligon" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Insert Point" +msgstr "Inserează Punct" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Edit Polygon (Remove Point)" +msgstr "Editează Poligon (Elimină Punct)" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Remove Polygon And Point" +msgstr "Elimină Poligon Și Punct" + #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #: editor/plugins/animation_player_editor_plugin.cpp @@ -4401,6 +4398,16 @@ msgid "Move CanvasItem" msgstr "Editează ObiectulPânză" #: editor/plugins/canvas_item_editor_plugin.cpp +msgid "Presets for the anchors and margins values of a Control node." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp +msgid "" +"Children of containers have their anchors and margins values overridden by " +"their parent." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp msgid "Anchors only" msgstr "Doar ancore" @@ -5319,6 +5326,12 @@ msgid "Create UV Map" msgstr "Creare hartă UV" #: editor/plugins/polygon_2d_editor_plugin.cpp +msgid "" +"Polygon 2D has internal vertices, so it can no longer be edited in the " +"viewport." +msgstr "" + +#: editor/plugins/polygon_2d_editor_plugin.cpp #, fuzzy msgid "Create Polygon & UV" msgstr "Crează Poligon" @@ -6449,7 +6462,7 @@ msgid "Post" msgstr "" #: editor/plugins/spatial_editor_plugin.cpp -msgid "Name-less gizmo" +msgid "Nameless gizmo" msgstr "" #: editor/plugins/sprite_editor_plugin.cpp @@ -6529,8 +6542,14 @@ msgid "(empty)" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animations" -msgstr "" +#, fuzzy +msgid "Animations:" +msgstr "AnimaÈ›ie" + +#: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "New Animation" +msgstr "AnimaÈ›ie" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed (FPS):" @@ -6541,8 +6560,9 @@ msgid "Loop" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animation Frames" -msgstr "" +#, fuzzy +msgid "Animation Frames:" +msgstr "Nume AnimaÈ›ie:" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Insert Empty (Before)" @@ -7355,6 +7375,19 @@ msgstr "" #: editor/project_manager.cpp msgid "" +"The following project settings file does not specify the version of Godot " +"through which it was created.\n" +"\n" +"%s\n" +"\n" +"If you proceed with opening it, it will be converted to Godot's current " +"configuration file format.\n" +"Warning: You will not be able to open the project with previous versions of " +"the engine anymore." +msgstr "" + +#: editor/project_manager.cpp +msgid "" "The following project settings file was generated by an older engine " "version, and needs to be converted for this version:\n" "\n" @@ -8867,10 +8900,6 @@ msgid "Build Project" msgstr "" #: modules/mono/editor/mono_bottom_panel.cpp -msgid "Warnings" -msgstr "" - -#: modules/mono/editor/mono_bottom_panel.cpp msgid "View log" msgstr "Vizualizează fiÈ™iere log" @@ -9506,6 +9535,13 @@ msgid "" "ParallaxLayer node only works when set as child of a ParallaxBackground node." msgstr "" +#: scene/2d/particles_2d.cpp +msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles2D node instead. You can use the \"Convert to " +"CPUParticles\" option for this purpose." +msgstr "" + #: scene/2d/particles_2d.cpp scene/3d/particles.cpp msgid "" "A material to process the particles is not assigned, so no behavior is " @@ -9661,6 +9697,13 @@ msgstr "" #: scene/3d/particles.cpp msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles node instead. You can use the \"Convert to CPUParticles" +"\" option for this purpose." +msgstr "" + +#: scene/3d/particles.cpp +msgid "" "Nothing is visible because meshes have not been assigned to draw passes." msgstr "" @@ -9691,21 +9734,6 @@ msgstr "" msgid "Path property must point to a valid Spatial node to work." msgstr "" -#: scene/3d/scenario_fx.cpp -msgid "WorldEnvironment needs an Environment resource." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " -"this environment's Background Mode to Canvas (for 2D scenes)." -msgstr "" - #: scene/3d/soft_body.cpp msgid "This body will be ignored until you set a mesh" msgstr "" @@ -9729,6 +9757,21 @@ msgid "" "it as a child of a VehicleBody." msgstr "" +#: scene/3d/world_environment.cpp +msgid "WorldEnvironment needs an Environment resource." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " +"this environment's Background Mode to Canvas (for 2D scenes)." +msgstr "" + #: scene/animation/animation_blend_tree.cpp msgid "On BlendTree node '%s', animation not found: '%s'" msgstr "" @@ -9775,11 +9818,19 @@ msgid "This node has been deprecated. Use AnimationTree instead." msgstr "" #: scene/gui/color_picker.cpp +msgid "Pick a color from the screen." +msgstr "" + +#: scene/gui/color_picker.cpp msgid "Raw Mode" msgstr "" #: scene/gui/color_picker.cpp -msgid "Add current color as a preset" +msgid "Switch between hexadecimal and code values." +msgstr "" + +#: scene/gui/color_picker.cpp +msgid "Add current color as a preset." msgstr "" #: scene/gui/dialogs.cpp @@ -9864,6 +9915,16 @@ msgid "Varyings can only be assigned in vertex function." msgstr "" #, fuzzy +#~ msgid "Font Size:" +#~ msgstr "Dimensiunea Conturului:" + +#~ msgid "Line:" +#~ msgstr "Linie:" + +#~ msgid "Col:" +#~ msgstr "Col:" + +#, fuzzy #~ msgid "Split already exists." #~ msgstr "AutoLoad '%s' există deja!" diff --git a/editor/translations/ru.po b/editor/translations/ru.po index 901e7858ce..2bc51dcbfb 100644 --- a/editor/translations/ru.po +++ b/editor/translations/ru.po @@ -33,12 +33,15 @@ # ÐÑлан Снупов <aslan170505@gmail.com>, 2018. # Alexandr Eremeev <ae125529@gmail.com>, 2019. # Ruaguzov Michael <miha890r@gmail.com>, 2019. +# Alexander Danilov <modos189@protonmail.com>, 2019. +# Sergey Nakhov <true.stalin.exe@gmail.com>, 2019. +# Bumerang <it.bumerang@gmail.com>, 2019. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2019-01-26 21:22+0000\n" -"Last-Translator: Ruaguzov Michael <miha890r@gmail.com>\n" +"PO-Revision-Date: 2019-02-13 16:10+0000\n" +"Last-Translator: Bumerang <it.bumerang@gmail.com>\n" "Language-Team: Russian <https://hosted.weblate.org/projects/godot-engine/" "godot/ru/>\n" "Language: ru\n" @@ -58,7 +61,7 @@ msgstr "Ðеверный тип аргумента Ð´Ð»Ñ convert(), иÑÐ¿Ð¾Ð»Ñ #: modules/mono/glue/gd_glue.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp msgid "Not enough bytes for decoding bytes, or invalid format." -msgstr "Ðе хватает байтов Ð´Ð»Ñ Ð´ÐµÐºÐ¾Ð´Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð±Ð°Ð¹Ñ‚Ð¾Ð², или неверный формат." +msgstr "ÐедоÑтаточно байтов Ð´Ð»Ñ Ð´ÐµÐºÐ¾Ð´Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð±Ð°Ð¹Ñ‚Ð¾Ð² или неверный формат." #: core/math/expression.cpp msgid "Invalid input %i (not passed) in expression" @@ -571,21 +574,13 @@ msgstr "Отдалить" msgid "Reset Zoom" msgstr "СброÑить приближение" -#: editor/code_editor.cpp -msgid "Warnings:" -msgstr "ПредупреждениÑ:" - -#: editor/code_editor.cpp -msgid "Font Size:" -msgstr "Размер шрифта:" - -#: editor/code_editor.cpp -msgid "Line:" -msgstr "Строка:" +#: editor/code_editor.cpp modules/mono/editor/mono_bottom_panel.cpp +msgid "Warnings" +msgstr "ПредупреждениÑ" #: editor/code_editor.cpp -msgid "Col:" -msgstr "Стлб:" +msgid "Line and column numbers." +msgstr "" #: editor/connections_dialog.cpp msgid "Method in target Node must be specified!" @@ -886,8 +881,8 @@ msgstr "Удалить выбранные файлы?" #: editor/dependency_editor.cpp editor/editor_audio_buses.cpp #: editor/editor_file_dialog.cpp editor/editor_node.cpp #: editor/filesystem_dock.cpp editor/plugins/item_list_editor_plugin.cpp -#: editor/project_export.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_dock.cpp +#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp +#: editor/project_settings_editor.cpp editor/scene_tree_dock.cpp msgid "Delete" msgstr "Удалить" @@ -1143,8 +1138,9 @@ msgid "Add Bus" msgstr "Добавить" #: editor/editor_audio_buses.cpp -msgid "Create a new Bus Layout." -msgstr "Создать новую раÑкладку шины." +#, fuzzy +msgid "Add a new Audio Bus to this layout." +msgstr "Сохранить раÑкладку звуковой шины как..." #: editor/editor_audio_buses.cpp editor/editor_properties.cpp #: editor/plugins/animation_player_editor_plugin.cpp editor/property_editor.cpp @@ -1172,6 +1168,10 @@ msgstr "Загрузить по умолчанию" msgid "Load the default Bus Layout." msgstr "Загрузить раÑкладку шины по умолчанию." +#: editor/editor_audio_buses.cpp +msgid "Create a new Bus Layout." +msgstr "Создать новую раÑкладку шины." + #: editor/editor_autoload_settings.cpp msgid "Invalid name." msgstr "ÐедопуÑтимое имÑ." @@ -2419,7 +2419,8 @@ msgid "Save & Restart" msgstr "Сохранить и перезапуÑтить" #: editor/editor_node.cpp -msgid "Spins when the editor window repaints!" +#, fuzzy +msgid "Spins when the editor window redraws." msgstr "ВращаетÑÑ, когда окно редактора перериÑовываетÑÑ!" #: editor/editor_node.cpp @@ -3347,14 +3348,15 @@ msgid "Save scenes, re-import and restart" msgstr "" #: editor/import_dock.cpp -#, fuzzy msgid "Changing the type of an imported file requires editor restart." -msgstr "Ð”Ð»Ñ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð²Ð¸Ð´ÐµÐ¾Ð´Ñ€Ð°Ð¹Ð²ÐµÑ€Ð° необходим перезапуÑк редактора." +msgstr "Изменение типа импортированного файла потребует перезапуÑк редактора." #: editor/import_dock.cpp msgid "" "WARNING: Assets exist that use this resource, they may stop loading properly." msgstr "" +"Предупреждение: ÑущеÑтвуют объекты, которые иÑпользуют Ñтот реÑурÑ, они " +"могут переÑтать загружатьÑÑ Ð´Ð¾Ð»Ð¶Ð½Ñ‹Ð¼ образом." #: editor/inspector_dock.cpp msgid "Failed to load resource." @@ -3479,22 +3481,6 @@ msgid "Create Polygon" msgstr "Создать Полигон" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Edit Polygon" -msgstr "Редактировать полигон" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Insert Point" -msgstr "Ð’Ñтавить точку" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Edit Polygon (Remove Point)" -msgstr "Редактировать Полигон (удалить точку)" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Remove Polygon And Point" -msgstr "Удалить Полигон и Точку" - -#: editor/plugins/abstract_polygon_2d_editor.cpp #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp msgid "Create points." @@ -3515,6 +3501,22 @@ msgstr "" msgid "Erase points." msgstr "Удалить точки." +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Edit Polygon" +msgstr "Редактировать полигон" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Insert Point" +msgstr "Ð’Ñтавить точку" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Edit Polygon (Remove Point)" +msgstr "Редактировать Полигон (удалить точку)" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Remove Polygon And Point" +msgstr "Удалить Полигон и Точку" + #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #: editor/plugins/animation_player_editor_plugin.cpp @@ -4316,6 +4318,19 @@ msgid "Move CanvasItem" msgstr "ПеремеÑтить CanvasItem" #: editor/plugins/canvas_item_editor_plugin.cpp +msgid "Presets for the anchors and margins values of a Control node." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp +#, fuzzy +msgid "" +"Children of containers have their anchors and margins values overridden by " +"their parent." +msgstr "" +"Внимание: Положение и размер детей контейнера определÑетÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ их " +"родителÑми." + +#: editor/plugins/canvas_item_editor_plugin.cpp msgid "Anchors only" msgstr "Только ÑкорÑ" @@ -5221,6 +5236,12 @@ msgid "Create UV Map" msgstr "Создать UV карту" #: editor/plugins/polygon_2d_editor_plugin.cpp +msgid "" +"Polygon 2D has internal vertices, so it can no longer be edited in the " +"viewport." +msgstr "" + +#: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Create Polygon & UV" msgstr "Создать Полигон и UV" @@ -6311,7 +6332,7 @@ msgstr "ПоÑле" #: editor/plugins/spatial_editor_plugin.cpp #, fuzzy -msgid "Name-less gizmo" +msgid "Nameless gizmo" msgstr "БезымÑнный штуковина" #: editor/plugins/sprite_editor_plugin.cpp @@ -6388,10 +6409,16 @@ msgid "(empty)" msgstr "(пуÑто)" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animations" +#, fuzzy +msgid "Animations:" msgstr "Ðнимации" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "New Animation" +msgstr "ÐнимациÑ" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed (FPS):" msgstr "СкороÑть (FPS):" @@ -6400,7 +6427,8 @@ msgid "Loop" msgstr "Зациклить" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animation Frames" +#, fuzzy +msgid "Animation Frames:" msgstr "Кадры анимации" #: editor/plugins/sprite_frames_editor_plugin.cpp @@ -7157,7 +7185,7 @@ msgstr "" #: editor/project_manager.cpp msgid "OpenGL ES 3.0" -msgstr "" +msgstr "OpenGL ES 3.0" #: editor/project_manager.cpp msgid "" @@ -7196,6 +7224,27 @@ msgid "Are you sure to open more than one project?" msgstr "Ð’Ñ‹ уверены, что хотите открыть более одного проекта?" #: editor/project_manager.cpp +#, fuzzy +msgid "" +"The following project settings file does not specify the version of Godot " +"through which it was created.\n" +"\n" +"%s\n" +"\n" +"If you proceed with opening it, it will be converted to Godot's current " +"configuration file format.\n" +"Warning: You will not be able to open the project with previous versions of " +"the engine anymore." +msgstr "" +"Файл наÑтроек проекта был Ñгенерирован Ñтарой верÑией движка и должен быть " +"преобразован Ð´Ð»Ñ Ñ‚ÐµÐºÑƒÑ‰ÐµÐ¹ верÑии:\n" +"\n" +"%s\n" +"\n" +"Ð’Ñ‹ хотите преобразовать его?\n" +"Внимание: Ð’Ñ‹ больше не Ñможете открыть проект предыдущими верÑиÑми движка." + +#: editor/project_manager.cpp msgid "" "The following project settings file was generated by an older engine " "version, and needs to be converted for this version:\n" @@ -8730,10 +8779,6 @@ msgid "Build Project" msgstr "Собрать проект" #: modules/mono/editor/mono_bottom_panel.cpp -msgid "Warnings" -msgstr "ПредупреждениÑ" - -#: modules/mono/editor/mono_bottom_panel.cpp msgid "View log" msgstr "ПроÑмотр журнала" @@ -9405,6 +9450,13 @@ msgstr "" "Узел ParallaxLayer работает только при уÑтановке его в качеÑтве дочернего " "узла ParallaxBackground." +#: scene/2d/particles_2d.cpp +msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles2D node instead. You can use the \"Convert to " +"CPUParticles\" option for this purpose." +msgstr "" + #: scene/2d/particles_2d.cpp scene/3d/particles.cpp msgid "" "A material to process the particles is not assigned, so no behavior is " @@ -9597,6 +9649,13 @@ msgstr "" #: scene/3d/particles.cpp msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles node instead. You can use the \"Convert to CPUParticles" +"\" option for this purpose." +msgstr "" + +#: scene/3d/particles.cpp +msgid "" "Nothing is visible because meshes have not been assigned to draw passes." msgstr "Ðичего не видно, потому что полиÑетки не были назначены на отриÑовку." @@ -9634,25 +9693,6 @@ msgstr "" msgid "Path property must point to a valid Spatial node to work." msgstr "СвойÑтво Path должно указывать на дейÑтвительный Spatial узел." -#: scene/3d/scenario_fx.cpp -msgid "WorldEnvironment needs an Environment resource." -msgstr "WorldEnvironment необходим Environment реÑурÑ." - -#: scene/3d/scenario_fx.cpp -msgid "" -"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." -msgstr "" -"Только один WorldEnvironment допуÑкаетÑÑ Ð½Ð° Ñцену или ÑовокупноÑть " -"приведённых Ñцен." - -#: scene/3d/scenario_fx.cpp -msgid "" -"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " -"this environment's Background Mode to Canvas (for 2D scenes)." -msgstr "" -"Ðтот WorldEnvironment игнорируетÑÑ. Либо добавьте Camera (Ð´Ð»Ñ 3D-Ñцен), либо " -"уÑтановите в Environment реÑурÑе Background режим в Canvas (Ð´Ð»Ñ 2D Ñцен)." - #: scene/3d/soft_body.cpp msgid "This body will be ignored until you set a mesh" msgstr "Ðто тело будет игнорироватьÑÑ, пока вы не уÑтановите Ñетку" @@ -9684,6 +9724,25 @@ msgstr "" "VehicleWheel Ñлужит колеÑом Ð´Ð»Ñ VehicleBody. ПожалуйÑта, иÑпользуйте его как " "ребенка VehicleBody." +#: scene/3d/world_environment.cpp +msgid "WorldEnvironment needs an Environment resource." +msgstr "WorldEnvironment необходим Environment реÑурÑ." + +#: scene/3d/world_environment.cpp +msgid "" +"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." +msgstr "" +"Только один WorldEnvironment допуÑкаетÑÑ Ð½Ð° Ñцену или ÑовокупноÑть " +"приведённых Ñцен." + +#: scene/3d/world_environment.cpp +msgid "" +"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " +"this environment's Background Mode to Canvas (for 2D scenes)." +msgstr "" +"Ðтот WorldEnvironment игнорируетÑÑ. Либо добавьте Camera (Ð´Ð»Ñ 3D-Ñцен), либо " +"уÑтановите в Environment реÑурÑе Background режим в Canvas (Ð´Ð»Ñ 2D Ñцен)." + #: scene/animation/animation_blend_tree.cpp msgid "On BlendTree node '%s', animation not found: '%s'" msgstr "Ðа узле BlendTree '%s' Ð°Ð½Ð¸Ð¼Ð°Ñ†Ð¸Ñ Ð½Ðµ найдена: '%s'" @@ -9725,11 +9784,20 @@ msgid "This node has been deprecated. Use AnimationTree instead." msgstr "Ðтот узел был удален. ВмеÑто Ñтого иÑпользуйте AnimationTree." #: scene/gui/color_picker.cpp +msgid "Pick a color from the screen." +msgstr "" + +#: scene/gui/color_picker.cpp msgid "Raw Mode" msgstr "RAW режим" #: scene/gui/color_picker.cpp -msgid "Add current color as a preset" +msgid "Switch between hexadecimal and code values." +msgstr "" + +#: scene/gui/color_picker.cpp +#, fuzzy +msgid "Add current color as a preset." msgstr "Добавить текущий цвет как преÑет" #: scene/gui/dialogs.cpp @@ -9829,6 +9897,18 @@ msgstr "Ðазначить форму" msgid "Varyings can only be assigned in vertex function." msgstr "Переменные могут быть назначены только в функции вершин." +#~ msgid "Warnings:" +#~ msgstr "ПредупреждениÑ:" + +#~ msgid "Font Size:" +#~ msgstr "Размер шрифта:" + +#~ msgid "Line:" +#~ msgstr "Строка:" + +#~ msgid "Col:" +#~ msgstr "Стлб:" + #~ msgid "OrientedPathFollow only works when set as a child of a Path node." #~ msgstr "OrientedPathFollow работает только еÑли она дочь узла Path." diff --git a/editor/translations/si.po b/editor/translations/si.po index 286cddb867..edceca5c8b 100644 --- a/editor/translations/si.po +++ b/editor/translations/si.po @@ -536,20 +536,12 @@ msgstr "" msgid "Reset Zoom" msgstr "" -#: editor/code_editor.cpp -msgid "Warnings:" -msgstr "" - -#: editor/code_editor.cpp -msgid "Font Size:" -msgstr "" - -#: editor/code_editor.cpp -msgid "Line:" +#: editor/code_editor.cpp modules/mono/editor/mono_bottom_panel.cpp +msgid "Warnings" msgstr "" #: editor/code_editor.cpp -msgid "Col:" +msgid "Line and column numbers." msgstr "" #: editor/connections_dialog.cpp @@ -843,8 +835,8 @@ msgstr "" #: editor/dependency_editor.cpp editor/editor_audio_buses.cpp #: editor/editor_file_dialog.cpp editor/editor_node.cpp #: editor/filesystem_dock.cpp editor/plugins/item_list_editor_plugin.cpp -#: editor/project_export.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_dock.cpp +#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp +#: editor/project_settings_editor.cpp editor/scene_tree_dock.cpp msgid "Delete" msgstr "" @@ -1096,7 +1088,7 @@ msgid "Add Bus" msgstr "" #: editor/editor_audio_buses.cpp -msgid "Create a new Bus Layout." +msgid "Add a new Audio Bus to this layout." msgstr "" #: editor/editor_audio_buses.cpp editor/editor_properties.cpp @@ -1125,6 +1117,10 @@ msgstr "" msgid "Load the default Bus Layout." msgstr "" +#: editor/editor_audio_buses.cpp +msgid "Create a new Bus Layout." +msgstr "" + #: editor/editor_autoload_settings.cpp msgid "Invalid name." msgstr "" @@ -2295,7 +2291,7 @@ msgid "Save & Restart" msgstr "" #: editor/editor_node.cpp -msgid "Spins when the editor window repaints!" +msgid "Spins when the editor window redraws." msgstr "" #: editor/editor_node.cpp @@ -3333,37 +3329,37 @@ msgid "Create Polygon" msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Edit Polygon" +#: editor/plugins/animation_blend_space_1d_editor.cpp +#: editor/plugins/animation_blend_space_2d_editor.cpp +msgid "Create points." msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Insert Point" +msgid "" +"Edit points.\n" +"LMB: Move Point\n" +"RMB: Erase Point" msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Edit Polygon (Remove Point)" +#: editor/plugins/animation_blend_space_1d_editor.cpp +msgid "Erase points." msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Remove Polygon And Point" +msgid "Edit Polygon" msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -#: editor/plugins/animation_blend_space_1d_editor.cpp -#: editor/plugins/animation_blend_space_2d_editor.cpp -msgid "Create points." +msgid "Insert Point" msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "" -"Edit points.\n" -"LMB: Move Point\n" -"RMB: Erase Point" +msgid "Edit Polygon (Remove Point)" msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -#: editor/plugins/animation_blend_space_1d_editor.cpp -msgid "Erase points." +msgid "Remove Polygon And Point" msgstr "" #: editor/plugins/animation_blend_space_1d_editor.cpp @@ -4146,6 +4142,16 @@ msgid "Move CanvasItem" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp +msgid "Presets for the anchors and margins values of a Control node." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp +msgid "" +"Children of containers have their anchors and margins values overridden by " +"their parent." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp msgid "Anchors only" msgstr "" @@ -5041,6 +5047,12 @@ msgid "Create UV Map" msgstr "" #: editor/plugins/polygon_2d_editor_plugin.cpp +msgid "" +"Polygon 2D has internal vertices, so it can no longer be edited in the " +"viewport." +msgstr "" + +#: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Create Polygon & UV" msgstr "" @@ -6123,7 +6135,7 @@ msgid "Post" msgstr "" #: editor/plugins/spatial_editor_plugin.cpp -msgid "Name-less gizmo" +msgid "Nameless gizmo" msgstr "" #: editor/plugins/sprite_editor_plugin.cpp @@ -6199,8 +6211,14 @@ msgid "(empty)" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animations" -msgstr "" +#, fuzzy +msgid "Animations:" +msgstr "à·à·Šâ€à¶»à·’à¶:" + +#: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "New Animation" +msgstr "සජීවීකරණ පුනරà·à·€à¶»à·Šà¶®à¶±à¶º" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed (FPS):" @@ -6211,7 +6229,7 @@ msgid "Loop" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animation Frames" +msgid "Animation Frames:" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp @@ -6990,6 +7008,19 @@ msgstr "" #: editor/project_manager.cpp msgid "" +"The following project settings file does not specify the version of Godot " +"through which it was created.\n" +"\n" +"%s\n" +"\n" +"If you proceed with opening it, it will be converted to Godot's current " +"configuration file format.\n" +"Warning: You will not be able to open the project with previous versions of " +"the engine anymore." +msgstr "" + +#: editor/project_manager.cpp +msgid "" "The following project settings file was generated by an older engine " "version, and needs to be converted for this version:\n" "\n" @@ -8466,10 +8497,6 @@ msgid "Build Project" msgstr "" #: modules/mono/editor/mono_bottom_panel.cpp -msgid "Warnings" -msgstr "" - -#: modules/mono/editor/mono_bottom_panel.cpp msgid "View log" msgstr "" @@ -9095,6 +9122,13 @@ msgid "" "ParallaxLayer node only works when set as child of a ParallaxBackground node." msgstr "" +#: scene/2d/particles_2d.cpp +msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles2D node instead. You can use the \"Convert to " +"CPUParticles\" option for this purpose." +msgstr "" + #: scene/2d/particles_2d.cpp scene/3d/particles.cpp msgid "" "A material to process the particles is not assigned, so no behavior is " @@ -9250,6 +9284,13 @@ msgstr "" #: scene/3d/particles.cpp msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles node instead. You can use the \"Convert to CPUParticles" +"\" option for this purpose." +msgstr "" + +#: scene/3d/particles.cpp +msgid "" "Nothing is visible because meshes have not been assigned to draw passes." msgstr "" @@ -9280,21 +9321,6 @@ msgstr "" msgid "Path property must point to a valid Spatial node to work." msgstr "" -#: scene/3d/scenario_fx.cpp -msgid "WorldEnvironment needs an Environment resource." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " -"this environment's Background Mode to Canvas (for 2D scenes)." -msgstr "" - #: scene/3d/soft_body.cpp msgid "This body will be ignored until you set a mesh" msgstr "" @@ -9318,6 +9344,21 @@ msgid "" "it as a child of a VehicleBody." msgstr "" +#: scene/3d/world_environment.cpp +msgid "WorldEnvironment needs an Environment resource." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " +"this environment's Background Mode to Canvas (for 2D scenes)." +msgstr "" + #: scene/animation/animation_blend_tree.cpp msgid "On BlendTree node '%s', animation not found: '%s'" msgstr "" @@ -9359,11 +9400,19 @@ msgid "This node has been deprecated. Use AnimationTree instead." msgstr "" #: scene/gui/color_picker.cpp +msgid "Pick a color from the screen." +msgstr "" + +#: scene/gui/color_picker.cpp msgid "Raw Mode" msgstr "" #: scene/gui/color_picker.cpp -msgid "Add current color as a preset" +msgid "Switch between hexadecimal and code values." +msgstr "" + +#: scene/gui/color_picker.cpp +msgid "Add current color as a preset." msgstr "" #: scene/gui/dialogs.cpp diff --git a/editor/translations/sk.po b/editor/translations/sk.po index 3ba9f42b94..afe61af6ce 100644 --- a/editor/translations/sk.po +++ b/editor/translations/sk.po @@ -4,12 +4,13 @@ # This file is distributed under the same license as the Godot source code. # J08nY <johnenter@gmail.com>, 2016. # MineGame 159 <minegame459@gmail.com>, 2018. +# Zuzana Palenikova <sousana.is@gmail.com>, 2019. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2018-12-13 14:42+0100\n" -"Last-Translator: MineGame 159 <minegame459@gmail.com>\n" +"PO-Revision-Date: 2019-02-01 12:10+0000\n" +"Last-Translator: Zuzana Palenikova <sousana.is@gmail.com>\n" "Language-Team: Slovak <https://hosted.weblate.org/projects/godot-engine/" "godot/sk/>\n" "Language: sk\n" @@ -17,7 +18,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" -"X-Generator: Poedit 2.2\n" +"X-Generator: Weblate 3.5-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -35,29 +36,29 @@ msgid "Invalid input %i (not passed) in expression" msgstr "" #: core/math/expression.cpp +#, fuzzy msgid "self can't be used because instance is null (not passed)" -msgstr "" +msgstr "self nemožno použiÅ¥ lebo inÅ¡tancia je rovná null (not passed)" #: core/math/expression.cpp msgid "Invalid operands to operator %s, %s and %s." -msgstr "" +msgstr "Neplatné operandy pre operátor %s, %s a %s." #: core/math/expression.cpp msgid "Invalid index of type %s for base type %s" -msgstr "" +msgstr "Neplatný index typu %s pre základný typ %s" #: core/math/expression.cpp msgid "Invalid named index '%s' for base type %s" -msgstr "" +msgstr "Neplatný názov indexu '%s' pre základný typ %s" #: core/math/expression.cpp -#, fuzzy msgid "Invalid arguments to construct '%s'" -msgstr "Chybný argument convert(), použite TYPE_* konÅ¡tanty." +msgstr "Neplatné argumenty pre vytvorenie '%s'" #: core/math/expression.cpp msgid "On call to '%s':" -msgstr "" +msgstr "Pri volanà '%s':" #: editor/animation_bezier_editor.cpp #: editor/plugins/asset_library_editor_plugin.cpp @@ -66,24 +67,23 @@ msgstr "" #: editor/animation_bezier_editor.cpp msgid "Balanced" -msgstr "" +msgstr "Vyvážený" #: editor/animation_bezier_editor.cpp msgid "Mirror" -msgstr "" +msgstr "Zrkadlový" #: editor/animation_bezier_editor.cpp msgid "Insert Key Here" -msgstr "" +msgstr "VložiÅ¥ tu kľúÄ" #: editor/animation_bezier_editor.cpp -#, fuzzy msgid "Duplicate Selected Key(s)" -msgstr "DuplikovaÅ¥ výber" +msgstr "DuplikovaÅ¥ kľúÄ(e)" #: editor/animation_bezier_editor.cpp msgid "Delete Selected Key(s)" -msgstr "" +msgstr "ZmazaÅ¥ kľúÄ(e)" #: editor/animation_bezier_editor.cpp editor/animation_track_editor.cpp msgid "Anim Duplicate Keys" @@ -543,20 +543,12 @@ msgstr "" msgid "Reset Zoom" msgstr "" -#: editor/code_editor.cpp -msgid "Warnings:" -msgstr "" - -#: editor/code_editor.cpp -msgid "Font Size:" -msgstr "" - -#: editor/code_editor.cpp -msgid "Line:" +#: editor/code_editor.cpp modules/mono/editor/mono_bottom_panel.cpp +msgid "Warnings" msgstr "" #: editor/code_editor.cpp -msgid "Col:" +msgid "Line and column numbers." msgstr "" #: editor/connections_dialog.cpp @@ -853,8 +845,8 @@ msgstr "" #: editor/dependency_editor.cpp editor/editor_audio_buses.cpp #: editor/editor_file_dialog.cpp editor/editor_node.cpp #: editor/filesystem_dock.cpp editor/plugins/item_list_editor_plugin.cpp -#: editor/project_export.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_dock.cpp +#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp +#: editor/project_settings_editor.cpp editor/scene_tree_dock.cpp msgid "Delete" msgstr "" @@ -1110,7 +1102,7 @@ msgid "Add Bus" msgstr "" #: editor/editor_audio_buses.cpp -msgid "Create a new Bus Layout." +msgid "Add a new Audio Bus to this layout." msgstr "" #: editor/editor_audio_buses.cpp editor/editor_properties.cpp @@ -1140,6 +1132,10 @@ msgstr "" msgid "Load the default Bus Layout." msgstr "" +#: editor/editor_audio_buses.cpp +msgid "Create a new Bus Layout." +msgstr "" + #: editor/editor_autoload_settings.cpp msgid "Invalid name." msgstr "" @@ -2335,7 +2331,7 @@ msgid "Save & Restart" msgstr "UložiÅ¥ súbor" #: editor/editor_node.cpp -msgid "Spins when the editor window repaints!" +msgid "Spins when the editor window redraws." msgstr "" #: editor/editor_node.cpp @@ -3396,24 +3392,6 @@ msgid "Create Polygon" msgstr "VytvoriÅ¥ adresár" #: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Edit Polygon" -msgstr "Signály:" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Insert Point" -msgstr "" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Edit Polygon (Remove Point)" -msgstr "" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Remove Polygon And Point" -msgstr "VÅ¡etky vybrané" - -#: editor/plugins/abstract_polygon_2d_editor.cpp #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #, fuzzy @@ -3433,6 +3411,24 @@ msgstr "" msgid "Erase points." msgstr "VÅ¡etky vybrané" +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Edit Polygon" +msgstr "Signály:" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Insert Point" +msgstr "" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Edit Polygon (Remove Point)" +msgstr "" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Remove Polygon And Point" +msgstr "VÅ¡etky vybrané" + #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #: editor/plugins/animation_player_editor_plugin.cpp @@ -4228,6 +4224,16 @@ msgid "Move CanvasItem" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp +msgid "Presets for the anchors and margins values of a Control node." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp +msgid "" +"Children of containers have their anchors and margins values overridden by " +"their parent." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp msgid "Anchors only" msgstr "" @@ -5136,6 +5142,12 @@ msgid "Create UV Map" msgstr "" #: editor/plugins/polygon_2d_editor_plugin.cpp +msgid "" +"Polygon 2D has internal vertices, so it can no longer be edited in the " +"viewport." +msgstr "" + +#: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Create Polygon & UV" msgstr "" @@ -6239,7 +6251,7 @@ msgid "Post" msgstr "" #: editor/plugins/spatial_editor_plugin.cpp -msgid "Name-less gizmo" +msgid "Nameless gizmo" msgstr "" #: editor/plugins/sprite_editor_plugin.cpp @@ -6316,7 +6328,12 @@ msgid "(empty)" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animations" +#, fuzzy +msgid "Animations:" +msgstr "Popis:" + +#: editor/plugins/sprite_frames_editor_plugin.cpp +msgid "New Animation" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp @@ -6328,8 +6345,9 @@ msgid "Loop" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animation Frames" -msgstr "" +#, fuzzy +msgid "Animation Frames:" +msgstr "Popis:" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Insert Empty (Before)" @@ -7139,6 +7157,19 @@ msgstr "" #: editor/project_manager.cpp msgid "" +"The following project settings file does not specify the version of Godot " +"through which it was created.\n" +"\n" +"%s\n" +"\n" +"If you proceed with opening it, it will be converted to Godot's current " +"configuration file format.\n" +"Warning: You will not be able to open the project with previous versions of " +"the engine anymore." +msgstr "" + +#: editor/project_manager.cpp +msgid "" "The following project settings file was generated by an older engine " "version, and needs to be converted for this version:\n" "\n" @@ -8644,10 +8675,6 @@ msgid "Build Project" msgstr "" #: modules/mono/editor/mono_bottom_panel.cpp -msgid "Warnings" -msgstr "" - -#: modules/mono/editor/mono_bottom_panel.cpp #, fuzzy msgid "View log" msgstr "Súbor:" @@ -9297,6 +9324,13 @@ msgid "" "ParallaxLayer node only works when set as child of a ParallaxBackground node." msgstr "" +#: scene/2d/particles_2d.cpp +msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles2D node instead. You can use the \"Convert to " +"CPUParticles\" option for this purpose." +msgstr "" + #: scene/2d/particles_2d.cpp scene/3d/particles.cpp msgid "" "A material to process the particles is not assigned, so no behavior is " @@ -9452,6 +9486,13 @@ msgstr "" #: scene/3d/particles.cpp msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles node instead. You can use the \"Convert to CPUParticles" +"\" option for this purpose." +msgstr "" + +#: scene/3d/particles.cpp +msgid "" "Nothing is visible because meshes have not been assigned to draw passes." msgstr "" @@ -9482,21 +9523,6 @@ msgstr "" msgid "Path property must point to a valid Spatial node to work." msgstr "" -#: scene/3d/scenario_fx.cpp -msgid "WorldEnvironment needs an Environment resource." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " -"this environment's Background Mode to Canvas (for 2D scenes)." -msgstr "" - #: scene/3d/soft_body.cpp msgid "This body will be ignored until you set a mesh" msgstr "" @@ -9520,6 +9546,21 @@ msgid "" "it as a child of a VehicleBody." msgstr "" +#: scene/3d/world_environment.cpp +msgid "WorldEnvironment needs an Environment resource." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " +"this environment's Background Mode to Canvas (for 2D scenes)." +msgstr "" + #: scene/animation/animation_blend_tree.cpp msgid "On BlendTree node '%s', animation not found: '%s'" msgstr "" @@ -9562,11 +9603,19 @@ msgid "This node has been deprecated. Use AnimationTree instead." msgstr "" #: scene/gui/color_picker.cpp +msgid "Pick a color from the screen." +msgstr "" + +#: scene/gui/color_picker.cpp msgid "Raw Mode" msgstr "" #: scene/gui/color_picker.cpp -msgid "Add current color as a preset" +msgid "Switch between hexadecimal and code values." +msgstr "" + +#: scene/gui/color_picker.cpp +msgid "Add current color as a preset." msgstr "" #: scene/gui/dialogs.cpp diff --git a/editor/translations/sl.po b/editor/translations/sl.po index 23b3436ef7..1974908006 100644 --- a/editor/translations/sl.po +++ b/editor/translations/sl.po @@ -561,22 +561,14 @@ msgstr "Oddalji" msgid "Reset Zoom" msgstr "Ponastavi PoveÄavo/PomanjÅ¡avo" -#: editor/code_editor.cpp -msgid "Warnings:" +#: editor/code_editor.cpp modules/mono/editor/mono_bottom_panel.cpp +msgid "Warnings" msgstr "" #: editor/code_editor.cpp -msgid "Font Size:" +msgid "Line and column numbers." msgstr "" -#: editor/code_editor.cpp -msgid "Line:" -msgstr "Vrstica:" - -#: editor/code_editor.cpp -msgid "Col:" -msgstr "Stolpec:" - #: editor/connections_dialog.cpp msgid "Method in target Node must be specified!" msgstr "Metoda v ciljnem gradniku mora biti navedena!" @@ -883,8 +875,8 @@ msgstr "IzbriÅ¡em izbrane datoteke?" #: editor/dependency_editor.cpp editor/editor_audio_buses.cpp #: editor/editor_file_dialog.cpp editor/editor_node.cpp #: editor/filesystem_dock.cpp editor/plugins/item_list_editor_plugin.cpp -#: editor/project_export.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_dock.cpp +#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp +#: editor/project_settings_editor.cpp editor/scene_tree_dock.cpp msgid "Delete" msgstr "IzbriÅ¡i" @@ -1141,8 +1133,9 @@ msgid "Add Bus" msgstr "Dodaj Vodilo" #: editor/editor_audio_buses.cpp -msgid "Create a new Bus Layout." -msgstr "Ustvari novo Postavitev Vodila." +#, fuzzy +msgid "Add a new Audio Bus to this layout." +msgstr "Shrani Postavitev ZvoÄnega Vodila Kot..." #: editor/editor_audio_buses.cpp editor/editor_properties.cpp #: editor/plugins/animation_player_editor_plugin.cpp editor/property_editor.cpp @@ -1170,6 +1163,10 @@ msgstr "Naložite Prevzeto" msgid "Load the default Bus Layout." msgstr "Naloži prevezeto Postavitev Vodila." +#: editor/editor_audio_buses.cpp +msgid "Create a new Bus Layout." +msgstr "Ustvari novo Postavitev Vodila." + #: editor/editor_autoload_settings.cpp msgid "Invalid name." msgstr "Neveljavno ime." @@ -2432,7 +2429,8 @@ msgid "Save & Restart" msgstr "Shrani & Zapri" #: editor/editor_node.cpp -msgid "Spins when the editor window repaints!" +#, fuzzy +msgid "Spins when the editor window redraws." msgstr "Vrti se ob spremembi okna urejevalnika!" #: editor/editor_node.cpp @@ -3527,25 +3525,6 @@ msgid "Create Polygon" msgstr "Ustvarite Poligon" #: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Edit Polygon" -msgstr "Uredi Poligon" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Insert Point" -msgstr "Ustavi ToÄko" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Edit Polygon (Remove Point)" -msgstr "Uredi Poligon (Odstrani ToÄko)" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Remove Polygon And Point" -msgstr "Odstrani Poligon in ToÄko" - -#: editor/plugins/abstract_polygon_2d_editor.cpp #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #, fuzzy @@ -3570,6 +3549,25 @@ msgstr "" msgid "Erase points." msgstr "IzbriÅ¡i toÄke" +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Edit Polygon" +msgstr "Uredi Poligon" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Insert Point" +msgstr "Ustavi ToÄko" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Edit Polygon (Remove Point)" +msgstr "Uredi Poligon (Odstrani ToÄko)" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Remove Polygon And Point" +msgstr "Odstrani Poligon in ToÄko" + #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #: editor/plugins/animation_player_editor_plugin.cpp @@ -4385,6 +4383,16 @@ msgid "Move CanvasItem" msgstr "Uredi Platno Stvari" #: editor/plugins/canvas_item_editor_plugin.cpp +msgid "Presets for the anchors and margins values of a Control node." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp +msgid "" +"Children of containers have their anchors and margins values overridden by " +"their parent." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp msgid "Anchors only" msgstr "Samo SidriÅ¡Äa" @@ -5295,6 +5303,12 @@ msgid "Create UV Map" msgstr "" #: editor/plugins/polygon_2d_editor_plugin.cpp +msgid "" +"Polygon 2D has internal vertices, so it can no longer be edited in the " +"viewport." +msgstr "" + +#: editor/plugins/polygon_2d_editor_plugin.cpp #, fuzzy msgid "Create Polygon & UV" msgstr "Ustvarite Poligon" @@ -6423,7 +6437,7 @@ msgid "Post" msgstr "" #: editor/plugins/spatial_editor_plugin.cpp -msgid "Name-less gizmo" +msgid "Nameless gizmo" msgstr "" #: editor/plugins/sprite_editor_plugin.cpp @@ -6503,8 +6517,14 @@ msgid "(empty)" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animations" -msgstr "" +#, fuzzy +msgid "Animations:" +msgstr "Animacija" + +#: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "New Animation" +msgstr "Animacija" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed (FPS):" @@ -6515,8 +6535,9 @@ msgid "Loop" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animation Frames" -msgstr "" +#, fuzzy +msgid "Animation Frames:" +msgstr "Ime Animacije:" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Insert Empty (Before)" @@ -7334,6 +7355,19 @@ msgstr "" #: editor/project_manager.cpp msgid "" +"The following project settings file does not specify the version of Godot " +"through which it was created.\n" +"\n" +"%s\n" +"\n" +"If you proceed with opening it, it will be converted to Godot's current " +"configuration file format.\n" +"Warning: You will not be able to open the project with previous versions of " +"the engine anymore." +msgstr "" + +#: editor/project_manager.cpp +msgid "" "The following project settings file was generated by an older engine " "version, and needs to be converted for this version:\n" "\n" @@ -8840,10 +8874,6 @@ msgid "Build Project" msgstr "" #: modules/mono/editor/mono_bottom_panel.cpp -msgid "Warnings" -msgstr "" - -#: modules/mono/editor/mono_bottom_panel.cpp #, fuzzy msgid "View log" msgstr "Ogled datotek" @@ -9502,6 +9532,13 @@ msgid "" "ParallaxLayer node only works when set as child of a ParallaxBackground node." msgstr "" +#: scene/2d/particles_2d.cpp +msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles2D node instead. You can use the \"Convert to " +"CPUParticles\" option for this purpose." +msgstr "" + #: scene/2d/particles_2d.cpp scene/3d/particles.cpp msgid "" "A material to process the particles is not assigned, so no behavior is " @@ -9657,6 +9694,13 @@ msgstr "" #: scene/3d/particles.cpp msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles node instead. You can use the \"Convert to CPUParticles" +"\" option for this purpose." +msgstr "" + +#: scene/3d/particles.cpp +msgid "" "Nothing is visible because meshes have not been assigned to draw passes." msgstr "" @@ -9687,21 +9731,6 @@ msgstr "" msgid "Path property must point to a valid Spatial node to work." msgstr "" -#: scene/3d/scenario_fx.cpp -msgid "WorldEnvironment needs an Environment resource." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " -"this environment's Background Mode to Canvas (for 2D scenes)." -msgstr "" - #: scene/3d/soft_body.cpp msgid "This body will be ignored until you set a mesh" msgstr "" @@ -9725,6 +9754,21 @@ msgid "" "it as a child of a VehicleBody." msgstr "" +#: scene/3d/world_environment.cpp +msgid "WorldEnvironment needs an Environment resource." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " +"this environment's Background Mode to Canvas (for 2D scenes)." +msgstr "" + #: scene/animation/animation_blend_tree.cpp msgid "On BlendTree node '%s', animation not found: '%s'" msgstr "" @@ -9772,11 +9816,20 @@ msgid "This node has been deprecated. Use AnimationTree instead." msgstr "" #: scene/gui/color_picker.cpp +msgid "Pick a color from the screen." +msgstr "" + +#: scene/gui/color_picker.cpp msgid "Raw Mode" msgstr "Neobdelan naÄin" #: scene/gui/color_picker.cpp -msgid "Add current color as a preset" +msgid "Switch between hexadecimal and code values." +msgstr "" + +#: scene/gui/color_picker.cpp +#, fuzzy +msgid "Add current color as a preset." msgstr "Dodaj trenutno barvo kot prednastavljeno" #: scene/gui/dialogs.cpp @@ -9863,6 +9916,12 @@ msgstr "" msgid "Varyings can only be assigned in vertex function." msgstr "" +#~ msgid "Line:" +#~ msgstr "Vrstica:" + +#~ msgid "Col:" +#~ msgstr "Stolpec:" + #, fuzzy #~ msgid "Split already exists." #~ msgstr "SamodejnoNalaganje '%s' že obstaja!" diff --git a/editor/translations/sq.po b/editor/translations/sq.po index ea81392f89..de9644d780 100644 --- a/editor/translations/sq.po +++ b/editor/translations/sq.po @@ -531,20 +531,12 @@ msgstr "" msgid "Reset Zoom" msgstr "" -#: editor/code_editor.cpp -msgid "Warnings:" -msgstr "" - -#: editor/code_editor.cpp -msgid "Font Size:" -msgstr "" - -#: editor/code_editor.cpp -msgid "Line:" +#: editor/code_editor.cpp modules/mono/editor/mono_bottom_panel.cpp +msgid "Warnings" msgstr "" #: editor/code_editor.cpp -msgid "Col:" +msgid "Line and column numbers." msgstr "" #: editor/connections_dialog.cpp @@ -838,8 +830,8 @@ msgstr "" #: editor/dependency_editor.cpp editor/editor_audio_buses.cpp #: editor/editor_file_dialog.cpp editor/editor_node.cpp #: editor/filesystem_dock.cpp editor/plugins/item_list_editor_plugin.cpp -#: editor/project_export.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_dock.cpp +#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp +#: editor/project_settings_editor.cpp editor/scene_tree_dock.cpp msgid "Delete" msgstr "" @@ -1091,7 +1083,7 @@ msgid "Add Bus" msgstr "" #: editor/editor_audio_buses.cpp -msgid "Create a new Bus Layout." +msgid "Add a new Audio Bus to this layout." msgstr "" #: editor/editor_audio_buses.cpp editor/editor_properties.cpp @@ -1120,6 +1112,10 @@ msgstr "" msgid "Load the default Bus Layout." msgstr "" +#: editor/editor_audio_buses.cpp +msgid "Create a new Bus Layout." +msgstr "" + #: editor/editor_autoload_settings.cpp msgid "Invalid name." msgstr "" @@ -2290,7 +2286,7 @@ msgid "Save & Restart" msgstr "" #: editor/editor_node.cpp -msgid "Spins when the editor window repaints!" +msgid "Spins when the editor window redraws." msgstr "" #: editor/editor_node.cpp @@ -3328,37 +3324,37 @@ msgid "Create Polygon" msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Edit Polygon" +#: editor/plugins/animation_blend_space_1d_editor.cpp +#: editor/plugins/animation_blend_space_2d_editor.cpp +msgid "Create points." msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Insert Point" +msgid "" +"Edit points.\n" +"LMB: Move Point\n" +"RMB: Erase Point" msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Edit Polygon (Remove Point)" +#: editor/plugins/animation_blend_space_1d_editor.cpp +msgid "Erase points." msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Remove Polygon And Point" +msgid "Edit Polygon" msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -#: editor/plugins/animation_blend_space_1d_editor.cpp -#: editor/plugins/animation_blend_space_2d_editor.cpp -msgid "Create points." +msgid "Insert Point" msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "" -"Edit points.\n" -"LMB: Move Point\n" -"RMB: Erase Point" +msgid "Edit Polygon (Remove Point)" msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -#: editor/plugins/animation_blend_space_1d_editor.cpp -msgid "Erase points." +msgid "Remove Polygon And Point" msgstr "" #: editor/plugins/animation_blend_space_1d_editor.cpp @@ -4141,6 +4137,16 @@ msgid "Move CanvasItem" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp +msgid "Presets for the anchors and margins values of a Control node." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp +msgid "" +"Children of containers have their anchors and margins values overridden by " +"their parent." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp msgid "Anchors only" msgstr "" @@ -5036,6 +5042,12 @@ msgid "Create UV Map" msgstr "" #: editor/plugins/polygon_2d_editor_plugin.cpp +msgid "" +"Polygon 2D has internal vertices, so it can no longer be edited in the " +"viewport." +msgstr "" + +#: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Create Polygon & UV" msgstr "" @@ -6117,7 +6129,7 @@ msgid "Post" msgstr "" #: editor/plugins/spatial_editor_plugin.cpp -msgid "Name-less gizmo" +msgid "Nameless gizmo" msgstr "" #: editor/plugins/sprite_editor_plugin.cpp @@ -6193,8 +6205,14 @@ msgid "(empty)" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animations" -msgstr "" +#, fuzzy +msgid "Animations:" +msgstr "Funksionet:" + +#: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "New Animation" +msgstr "Përmirëso Animacionin" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed (FPS):" @@ -6205,8 +6223,9 @@ msgid "Loop" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animation Frames" -msgstr "" +#, fuzzy +msgid "Animation Frames:" +msgstr "Karakteristikat e animacionit." #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Insert Empty (Before)" @@ -6983,6 +7002,19 @@ msgstr "" #: editor/project_manager.cpp msgid "" +"The following project settings file does not specify the version of Godot " +"through which it was created.\n" +"\n" +"%s\n" +"\n" +"If you proceed with opening it, it will be converted to Godot's current " +"configuration file format.\n" +"Warning: You will not be able to open the project with previous versions of " +"the engine anymore." +msgstr "" + +#: editor/project_manager.cpp +msgid "" "The following project settings file was generated by an older engine " "version, and needs to be converted for this version:\n" "\n" @@ -8459,10 +8491,6 @@ msgid "Build Project" msgstr "" #: modules/mono/editor/mono_bottom_panel.cpp -msgid "Warnings" -msgstr "" - -#: modules/mono/editor/mono_bottom_panel.cpp msgid "View log" msgstr "" @@ -9088,6 +9116,13 @@ msgid "" "ParallaxLayer node only works when set as child of a ParallaxBackground node." msgstr "" +#: scene/2d/particles_2d.cpp +msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles2D node instead. You can use the \"Convert to " +"CPUParticles\" option for this purpose." +msgstr "" + #: scene/2d/particles_2d.cpp scene/3d/particles.cpp msgid "" "A material to process the particles is not assigned, so no behavior is " @@ -9243,6 +9278,13 @@ msgstr "" #: scene/3d/particles.cpp msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles node instead. You can use the \"Convert to CPUParticles" +"\" option for this purpose." +msgstr "" + +#: scene/3d/particles.cpp +msgid "" "Nothing is visible because meshes have not been assigned to draw passes." msgstr "" @@ -9273,21 +9315,6 @@ msgstr "" msgid "Path property must point to a valid Spatial node to work." msgstr "" -#: scene/3d/scenario_fx.cpp -msgid "WorldEnvironment needs an Environment resource." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " -"this environment's Background Mode to Canvas (for 2D scenes)." -msgstr "" - #: scene/3d/soft_body.cpp msgid "This body will be ignored until you set a mesh" msgstr "" @@ -9311,6 +9338,21 @@ msgid "" "it as a child of a VehicleBody." msgstr "" +#: scene/3d/world_environment.cpp +msgid "WorldEnvironment needs an Environment resource." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " +"this environment's Background Mode to Canvas (for 2D scenes)." +msgstr "" + #: scene/animation/animation_blend_tree.cpp msgid "On BlendTree node '%s', animation not found: '%s'" msgstr "" @@ -9352,11 +9394,19 @@ msgid "This node has been deprecated. Use AnimationTree instead." msgstr "" #: scene/gui/color_picker.cpp +msgid "Pick a color from the screen." +msgstr "" + +#: scene/gui/color_picker.cpp msgid "Raw Mode" msgstr "" #: scene/gui/color_picker.cpp -msgid "Add current color as a preset" +msgid "Switch between hexadecimal and code values." +msgstr "" + +#: scene/gui/color_picker.cpp +msgid "Add current color as a preset." msgstr "" #: scene/gui/dialogs.cpp diff --git a/editor/translations/sr_Cyrl.po b/editor/translations/sr_Cyrl.po index b74074cda1..a4271de16b 100644 --- a/editor/translations/sr_Cyrl.po +++ b/editor/translations/sr_Cyrl.po @@ -561,22 +561,13 @@ msgstr "Умањи" msgid "Reset Zoom" msgstr "РеÑетуј увеличање" -#: editor/code_editor.cpp -msgid "Warnings:" +#: editor/code_editor.cpp modules/mono/editor/mono_bottom_panel.cpp +msgid "Warnings" msgstr "" #: editor/code_editor.cpp -#, fuzzy -msgid "Font Size:" -msgstr "Поглед иÑпред" - -#: editor/code_editor.cpp -msgid "Line:" -msgstr "Линија:" - -#: editor/code_editor.cpp -msgid "Col:" -msgstr "Колона:" +msgid "Line and column numbers." +msgstr "" #: editor/connections_dialog.cpp msgid "Method in target Node must be specified!" @@ -888,8 +879,8 @@ msgstr "Обриши одабране датотеке?" #: editor/dependency_editor.cpp editor/editor_audio_buses.cpp #: editor/editor_file_dialog.cpp editor/editor_node.cpp #: editor/filesystem_dock.cpp editor/plugins/item_list_editor_plugin.cpp -#: editor/project_export.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_dock.cpp +#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp +#: editor/project_settings_editor.cpp editor/scene_tree_dock.cpp msgid "Delete" msgstr "Обриши" @@ -1148,8 +1139,9 @@ msgid "Add Bus" msgstr "Додај баÑ" #: editor/editor_audio_buses.cpp -msgid "Create a new Bus Layout." -msgstr "Ðаправи нови Ð±Ð°Ñ Ñ€Ð°Ñпоред." +#, fuzzy +msgid "Add a new Audio Bus to this layout." +msgstr "Сачувај раÑпоред звучног баÑа као..." #: editor/editor_audio_buses.cpp editor/editor_properties.cpp #: editor/plugins/animation_player_editor_plugin.cpp editor/property_editor.cpp @@ -1177,6 +1169,10 @@ msgstr "Учитај уобичајено" msgid "Load the default Bus Layout." msgstr "Учитај уобичајен Ð±Ð°Ñ Ñ€Ð°Ñпоред." +#: editor/editor_audio_buses.cpp +msgid "Create a new Bus Layout." +msgstr "Ðаправи нови Ð±Ð°Ñ Ñ€Ð°Ñпоред." + #: editor/editor_autoload_settings.cpp msgid "Invalid name." msgstr "Ðеважеће име." @@ -2445,7 +2441,8 @@ msgid "Save & Restart" msgstr "Сачувај и изађи" #: editor/editor_node.cpp -msgid "Spins when the editor window repaints!" +#, fuzzy +msgid "Spins when the editor window redraws." msgstr "Окрене Ñе кад Ñе едиторÑки прозор поново обоји!" #: editor/editor_node.cpp @@ -3555,25 +3552,6 @@ msgid "Create Polygon" msgstr "Ðаправи полигон" #: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Edit Polygon" -msgstr "Измени полигон" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Insert Point" -msgstr "Уметни тачку" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Edit Polygon (Remove Point)" -msgstr "Уреди полигон (обриши тачку)" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Remove Polygon And Point" -msgstr "Обриши полигон и тачку" - -#: editor/plugins/abstract_polygon_2d_editor.cpp #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #, fuzzy @@ -3598,6 +3576,25 @@ msgstr "" msgid "Erase points." msgstr "ДеÑни таÑтер миша: обриши тачку." +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Edit Polygon" +msgstr "Измени полигон" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Insert Point" +msgstr "Уметни тачку" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Edit Polygon (Remove Point)" +msgstr "Уреди полигон (обриши тачку)" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Remove Polygon And Point" +msgstr "Обриши полигон и тачку" + #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #: editor/plugins/animation_player_editor_plugin.cpp @@ -4407,6 +4404,16 @@ msgid "Move CanvasItem" msgstr "Уреди CanvasItem" #: editor/plugins/canvas_item_editor_plugin.cpp +msgid "Presets for the anchors and margins values of a Control node." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp +msgid "" +"Children of containers have their anchors and margins values overridden by " +"their parent." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp msgid "Anchors only" msgstr "Само Ñидра" @@ -5327,6 +5334,12 @@ msgid "Create UV Map" msgstr "Ðаправи UV мапу" #: editor/plugins/polygon_2d_editor_plugin.cpp +msgid "" +"Polygon 2D has internal vertices, so it can no longer be edited in the " +"viewport." +msgstr "" + +#: editor/plugins/polygon_2d_editor_plugin.cpp #, fuzzy msgid "Create Polygon & UV" msgstr "Ðаправи полигон" @@ -6477,7 +6490,7 @@ msgid "Post" msgstr "ПоÑле" #: editor/plugins/spatial_editor_plugin.cpp -msgid "Name-less gizmo" +msgid "Nameless gizmo" msgstr "" #: editor/plugins/sprite_editor_plugin.cpp @@ -6559,10 +6572,16 @@ msgid "(empty)" msgstr "(празно)" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animations" +#, fuzzy +msgid "Animations:" msgstr "Ðнимације" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "New Animation" +msgstr "Ðнимација" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed (FPS):" msgstr "Брзина (FPS):" @@ -6572,7 +6591,8 @@ msgid "Loop" msgstr "ЦиклуÑ" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animation Frames" +#, fuzzy +msgid "Animation Frames:" msgstr "Ðнимационе Ñлике" #: editor/plugins/sprite_frames_editor_plugin.cpp @@ -7418,6 +7438,19 @@ msgstr "" #: editor/project_manager.cpp msgid "" +"The following project settings file does not specify the version of Godot " +"through which it was created.\n" +"\n" +"%s\n" +"\n" +"If you proceed with opening it, it will be converted to Godot's current " +"configuration file format.\n" +"Warning: You will not be able to open the project with previous versions of " +"the engine anymore." +msgstr "" + +#: editor/project_manager.cpp +msgid "" "The following project settings file was generated by an older engine " "version, and needs to be converted for this version:\n" "\n" @@ -8936,10 +8969,6 @@ msgid "Build Project" msgstr "Пројекат" #: modules/mono/editor/mono_bottom_panel.cpp -msgid "Warnings" -msgstr "" - -#: modules/mono/editor/mono_bottom_panel.cpp #, fuzzy msgid "View log" msgstr "Погледај датотеке" @@ -9582,6 +9611,13 @@ msgid "" "ParallaxLayer node only works when set as child of a ParallaxBackground node." msgstr "" +#: scene/2d/particles_2d.cpp +msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles2D node instead. You can use the \"Convert to " +"CPUParticles\" option for this purpose." +msgstr "" + #: scene/2d/particles_2d.cpp scene/3d/particles.cpp msgid "" "A material to process the particles is not assigned, so no behavior is " @@ -9737,6 +9773,13 @@ msgstr "" #: scene/3d/particles.cpp msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles node instead. You can use the \"Convert to CPUParticles" +"\" option for this purpose." +msgstr "" + +#: scene/3d/particles.cpp +msgid "" "Nothing is visible because meshes have not been assigned to draw passes." msgstr "" @@ -9767,21 +9810,6 @@ msgstr "" msgid "Path property must point to a valid Spatial node to work." msgstr "" -#: scene/3d/scenario_fx.cpp -msgid "WorldEnvironment needs an Environment resource." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " -"this environment's Background Mode to Canvas (for 2D scenes)." -msgstr "" - #: scene/3d/soft_body.cpp msgid "This body will be ignored until you set a mesh" msgstr "" @@ -9805,6 +9833,21 @@ msgid "" "it as a child of a VehicleBody." msgstr "" +#: scene/3d/world_environment.cpp +msgid "WorldEnvironment needs an Environment resource." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " +"this environment's Background Mode to Canvas (for 2D scenes)." +msgstr "" + #: scene/animation/animation_blend_tree.cpp msgid "On BlendTree node '%s', animation not found: '%s'" msgstr "" @@ -9851,11 +9894,19 @@ msgid "This node has been deprecated. Use AnimationTree instead." msgstr "" #: scene/gui/color_picker.cpp +msgid "Pick a color from the screen." +msgstr "" + +#: scene/gui/color_picker.cpp msgid "Raw Mode" msgstr "" #: scene/gui/color_picker.cpp -msgid "Add current color as a preset" +msgid "Switch between hexadecimal and code values." +msgstr "" + +#: scene/gui/color_picker.cpp +msgid "Add current color as a preset." msgstr "" #: scene/gui/dialogs.cpp @@ -9941,6 +9992,16 @@ msgid "Varyings can only be assigned in vertex function." msgstr "" #, fuzzy +#~ msgid "Font Size:" +#~ msgstr "Поглед иÑпред" + +#~ msgid "Line:" +#~ msgstr "Линија:" + +#~ msgid "Col:" +#~ msgstr "Колона:" + +#, fuzzy #~ msgid "Split already exists." #~ msgstr "ÐутоматÑко учитавање '%s' већ поÑтоји!" diff --git a/editor/translations/sr_Latn.po b/editor/translations/sr_Latn.po index 7a50fedd2c..46073472f7 100644 --- a/editor/translations/sr_Latn.po +++ b/editor/translations/sr_Latn.po @@ -544,20 +544,12 @@ msgstr "" msgid "Reset Zoom" msgstr "" -#: editor/code_editor.cpp -msgid "Warnings:" -msgstr "" - -#: editor/code_editor.cpp -msgid "Font Size:" -msgstr "" - -#: editor/code_editor.cpp -msgid "Line:" +#: editor/code_editor.cpp modules/mono/editor/mono_bottom_panel.cpp +msgid "Warnings" msgstr "" #: editor/code_editor.cpp -msgid "Col:" +msgid "Line and column numbers." msgstr "" #: editor/connections_dialog.cpp @@ -852,8 +844,8 @@ msgstr "" #: editor/dependency_editor.cpp editor/editor_audio_buses.cpp #: editor/editor_file_dialog.cpp editor/editor_node.cpp #: editor/filesystem_dock.cpp editor/plugins/item_list_editor_plugin.cpp -#: editor/project_export.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_dock.cpp +#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp +#: editor/project_settings_editor.cpp editor/scene_tree_dock.cpp msgid "Delete" msgstr "" @@ -1105,7 +1097,7 @@ msgid "Add Bus" msgstr "" #: editor/editor_audio_buses.cpp -msgid "Create a new Bus Layout." +msgid "Add a new Audio Bus to this layout." msgstr "" #: editor/editor_audio_buses.cpp editor/editor_properties.cpp @@ -1134,6 +1126,10 @@ msgstr "" msgid "Load the default Bus Layout." msgstr "" +#: editor/editor_audio_buses.cpp +msgid "Create a new Bus Layout." +msgstr "" + #: editor/editor_autoload_settings.cpp msgid "Invalid name." msgstr "" @@ -2305,7 +2301,7 @@ msgid "Save & Restart" msgstr "" #: editor/editor_node.cpp -msgid "Spins when the editor window repaints!" +msgid "Spins when the editor window redraws." msgstr "" #: editor/editor_node.cpp @@ -3344,39 +3340,39 @@ msgid "Create Polygon" msgstr "Napravi" #: editor/plugins/abstract_polygon_2d_editor.cpp +#: editor/plugins/animation_blend_space_1d_editor.cpp +#: editor/plugins/animation_blend_space_2d_editor.cpp #, fuzzy -msgid "Edit Polygon" +msgid "Create points." msgstr "Napravi" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Insert Point" -msgstr "" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Edit Polygon (Remove Point)" +msgid "" +"Edit points.\n" +"LMB: Move Point\n" +"RMB: Erase Point" msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Remove Polygon And Point" +#: editor/plugins/animation_blend_space_1d_editor.cpp +msgid "Erase points." msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -#: editor/plugins/animation_blend_space_1d_editor.cpp -#: editor/plugins/animation_blend_space_2d_editor.cpp #, fuzzy -msgid "Create points." +msgid "Edit Polygon" msgstr "Napravi" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "" -"Edit points.\n" -"LMB: Move Point\n" -"RMB: Erase Point" +msgid "Insert Point" msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -#: editor/plugins/animation_blend_space_1d_editor.cpp -msgid "Erase points." +msgid "Edit Polygon (Remove Point)" +msgstr "" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Remove Polygon And Point" msgstr "" #: editor/plugins/animation_blend_space_1d_editor.cpp @@ -4163,6 +4159,16 @@ msgid "Move CanvasItem" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp +msgid "Presets for the anchors and margins values of a Control node." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp +msgid "" +"Children of containers have their anchors and margins values overridden by " +"their parent." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp msgid "Anchors only" msgstr "" @@ -5061,6 +5067,12 @@ msgid "Create UV Map" msgstr "" #: editor/plugins/polygon_2d_editor_plugin.cpp +msgid "" +"Polygon 2D has internal vertices, so it can no longer be edited in the " +"viewport." +msgstr "" + +#: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Create Polygon & UV" msgstr "" @@ -6149,7 +6161,7 @@ msgid "Post" msgstr "" #: editor/plugins/spatial_editor_plugin.cpp -msgid "Name-less gizmo" +msgid "Nameless gizmo" msgstr "" #: editor/plugins/sprite_editor_plugin.cpp @@ -6226,8 +6238,14 @@ msgid "(empty)" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animations" -msgstr "" +#, fuzzy +msgid "Animations:" +msgstr "Optimizuj Animaciju" + +#: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "New Animation" +msgstr "Optimizuj Animaciju" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed (FPS):" @@ -6238,8 +6256,9 @@ msgid "Loop" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animation Frames" -msgstr "" +#, fuzzy +msgid "Animation Frames:" +msgstr "Optimizuj Animaciju" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Insert Empty (Before)" @@ -7030,6 +7049,19 @@ msgstr "" #: editor/project_manager.cpp msgid "" +"The following project settings file does not specify the version of Godot " +"through which it was created.\n" +"\n" +"%s\n" +"\n" +"If you proceed with opening it, it will be converted to Godot's current " +"configuration file format.\n" +"Warning: You will not be able to open the project with previous versions of " +"the engine anymore." +msgstr "" + +#: editor/project_manager.cpp +msgid "" "The following project settings file was generated by an older engine " "version, and needs to be converted for this version:\n" "\n" @@ -8511,10 +8543,6 @@ msgid "Build Project" msgstr "" #: modules/mono/editor/mono_bottom_panel.cpp -msgid "Warnings" -msgstr "" - -#: modules/mono/editor/mono_bottom_panel.cpp msgid "View log" msgstr "" @@ -9140,6 +9168,13 @@ msgid "" "ParallaxLayer node only works when set as child of a ParallaxBackground node." msgstr "" +#: scene/2d/particles_2d.cpp +msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles2D node instead. You can use the \"Convert to " +"CPUParticles\" option for this purpose." +msgstr "" + #: scene/2d/particles_2d.cpp scene/3d/particles.cpp msgid "" "A material to process the particles is not assigned, so no behavior is " @@ -9295,6 +9330,13 @@ msgstr "" #: scene/3d/particles.cpp msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles node instead. You can use the \"Convert to CPUParticles" +"\" option for this purpose." +msgstr "" + +#: scene/3d/particles.cpp +msgid "" "Nothing is visible because meshes have not been assigned to draw passes." msgstr "" @@ -9325,21 +9367,6 @@ msgstr "" msgid "Path property must point to a valid Spatial node to work." msgstr "" -#: scene/3d/scenario_fx.cpp -msgid "WorldEnvironment needs an Environment resource." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " -"this environment's Background Mode to Canvas (for 2D scenes)." -msgstr "" - #: scene/3d/soft_body.cpp msgid "This body will be ignored until you set a mesh" msgstr "" @@ -9363,6 +9390,21 @@ msgid "" "it as a child of a VehicleBody." msgstr "" +#: scene/3d/world_environment.cpp +msgid "WorldEnvironment needs an Environment resource." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " +"this environment's Background Mode to Canvas (for 2D scenes)." +msgstr "" + #: scene/animation/animation_blend_tree.cpp msgid "On BlendTree node '%s', animation not found: '%s'" msgstr "" @@ -9404,11 +9446,19 @@ msgid "This node has been deprecated. Use AnimationTree instead." msgstr "" #: scene/gui/color_picker.cpp +msgid "Pick a color from the screen." +msgstr "" + +#: scene/gui/color_picker.cpp msgid "Raw Mode" msgstr "" #: scene/gui/color_picker.cpp -msgid "Add current color as a preset" +msgid "Switch between hexadecimal and code values." +msgstr "" + +#: scene/gui/color_picker.cpp +msgid "Add current color as a preset." msgstr "" #: scene/gui/dialogs.cpp diff --git a/editor/translations/sv.po b/editor/translations/sv.po index 6071ea21a8..98c2593d34 100644 --- a/editor/translations/sv.po +++ b/editor/translations/sv.po @@ -580,23 +580,14 @@ msgstr "Zooma Ut" msgid "Reset Zoom" msgstr "Ã…terställ Zoom" -#: editor/code_editor.cpp +#: editor/code_editor.cpp modules/mono/editor/mono_bottom_panel.cpp #, fuzzy -msgid "Warnings:" +msgid "Warnings" msgstr "Varning" #: editor/code_editor.cpp -#, fuzzy -msgid "Font Size:" -msgstr "Vy framifrÃ¥n" - -#: editor/code_editor.cpp -msgid "Line:" -msgstr "Rad:" - -#: editor/code_editor.cpp -msgid "Col:" -msgstr "Kolumn:" +msgid "Line and column numbers." +msgstr "" #: editor/connections_dialog.cpp #, fuzzy @@ -939,8 +930,8 @@ msgstr "Ta bort valda filer?" #: editor/dependency_editor.cpp editor/editor_audio_buses.cpp #: editor/editor_file_dialog.cpp editor/editor_node.cpp #: editor/filesystem_dock.cpp editor/plugins/item_list_editor_plugin.cpp -#: editor/project_export.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_dock.cpp +#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp +#: editor/project_settings_editor.cpp editor/scene_tree_dock.cpp msgid "Delete" msgstr "Ta bort" @@ -1245,8 +1236,8 @@ msgstr "Lägg till Buss" #: editor/editor_audio_buses.cpp #, fuzzy -msgid "Create a new Bus Layout." -msgstr "Skapa en ny Buss-Layout." +msgid "Add a new Audio Bus to this layout." +msgstr "Spara Ljud-Buss Layout Som..." #: editor/editor_audio_buses.cpp editor/editor_properties.cpp #: editor/plugins/animation_player_editor_plugin.cpp editor/property_editor.cpp @@ -1279,6 +1270,11 @@ msgstr "Ladda Standard" msgid "Load the default Bus Layout." msgstr "Ladda standard Buss-Layouten." +#: editor/editor_audio_buses.cpp +#, fuzzy +msgid "Create a new Bus Layout." +msgstr "Skapa en ny Buss-Layout." + #: editor/editor_autoload_settings.cpp #, fuzzy msgid "Invalid name." @@ -2650,7 +2646,7 @@ msgid "Save & Restart" msgstr "Spara & Avsluta" #: editor/editor_node.cpp -msgid "Spins when the editor window repaints!" +msgid "Spins when the editor window redraws." msgstr "" #: editor/editor_node.cpp @@ -3795,25 +3791,6 @@ msgid "Create Polygon" msgstr "Skapa Prenumeration" #: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Edit Polygon" -msgstr "Redigera Polygon" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Insert Point" -msgstr "Infoga Punkt" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Edit Polygon (Remove Point)" -msgstr "Redigera Polygon (ta bort punkt)" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Remove Polygon And Point" -msgstr "Ta bort Polygon och Punkt" - -#: editor/plugins/abstract_polygon_2d_editor.cpp #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #, fuzzy @@ -3833,6 +3810,25 @@ msgstr "" msgid "Erase points." msgstr "Radera punkter" +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Edit Polygon" +msgstr "Redigera Polygon" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Insert Point" +msgstr "Infoga Punkt" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Edit Polygon (Remove Point)" +msgstr "Redigera Polygon (ta bort punkt)" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Remove Polygon And Point" +msgstr "Ta bort Polygon och Punkt" + #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #: editor/plugins/animation_player_editor_plugin.cpp @@ -4658,6 +4654,16 @@ msgid "Move CanvasItem" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp +msgid "Presets for the anchors and margins values of a Control node." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp +msgid "" +"Children of containers have their anchors and margins values overridden by " +"their parent." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp msgid "Anchors only" msgstr "" @@ -5582,6 +5588,12 @@ msgid "Create UV Map" msgstr "" #: editor/plugins/polygon_2d_editor_plugin.cpp +msgid "" +"Polygon 2D has internal vertices, so it can no longer be edited in the " +"viewport." +msgstr "" + +#: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Create Polygon & UV" msgstr "" @@ -6761,7 +6773,7 @@ msgid "Post" msgstr "" #: editor/plugins/spatial_editor_plugin.cpp -msgid "Name-less gizmo" +msgid "Nameless gizmo" msgstr "" #: editor/plugins/sprite_editor_plugin.cpp @@ -6843,10 +6855,16 @@ msgid "(empty)" msgstr "(tom)" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animations" +#, fuzzy +msgid "Animations:" msgstr "Animationer" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "New Animation" +msgstr "Animation" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed (FPS):" msgstr "" @@ -6856,8 +6874,9 @@ msgid "Loop" msgstr "Loop" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animation Frames" -msgstr "" +#, fuzzy +msgid "Animation Frames:" +msgstr "Nytt Animationsnamn:" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Insert Empty (Before)" @@ -7702,6 +7721,19 @@ msgstr "" #: editor/project_manager.cpp msgid "" +"The following project settings file does not specify the version of Godot " +"through which it was created.\n" +"\n" +"%s\n" +"\n" +"If you proceed with opening it, it will be converted to Godot's current " +"configuration file format.\n" +"Warning: You will not be able to open the project with previous versions of " +"the engine anymore." +msgstr "" + +#: editor/project_manager.cpp +msgid "" "The following project settings file was generated by an older engine " "version, and needs to be converted for this version:\n" "\n" @@ -9299,11 +9331,6 @@ msgstr "Projekt" #: modules/mono/editor/mono_bottom_panel.cpp #, fuzzy -msgid "Warnings" -msgstr "Varning" - -#: modules/mono/editor/mono_bottom_panel.cpp -#, fuzzy msgid "View log" msgstr "Visa Filer" @@ -9980,6 +10007,13 @@ msgstr "" "ParallaxLayer-Node fungerar bara när satt som en barn till en " "ParallaxBackground-Node." +#: scene/2d/particles_2d.cpp +msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles2D node instead. You can use the \"Convert to " +"CPUParticles\" option for this purpose." +msgstr "" + #: scene/2d/particles_2d.cpp scene/3d/particles.cpp msgid "" "A material to process the particles is not assigned, so no behavior is " @@ -10149,6 +10183,13 @@ msgstr "" #: scene/3d/particles.cpp msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles node instead. You can use the \"Convert to CPUParticles" +"\" option for this purpose." +msgstr "" + +#: scene/3d/particles.cpp +msgid "" "Nothing is visible because meshes have not been assigned to draw passes." msgstr "" @@ -10181,21 +10222,6 @@ msgstr "" msgid "Path property must point to a valid Spatial node to work." msgstr "" -#: scene/3d/scenario_fx.cpp -msgid "WorldEnvironment needs an Environment resource." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " -"this environment's Background Mode to Canvas (for 2D scenes)." -msgstr "" - #: scene/3d/soft_body.cpp msgid "This body will be ignored until you set a mesh" msgstr "" @@ -10219,6 +10245,21 @@ msgid "" "it as a child of a VehicleBody." msgstr "" +#: scene/3d/world_environment.cpp +msgid "WorldEnvironment needs an Environment resource." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " +"this environment's Background Mode to Canvas (for 2D scenes)." +msgstr "" + #: scene/animation/animation_blend_tree.cpp msgid "On BlendTree node '%s', animation not found: '%s'" msgstr "" @@ -10264,13 +10305,21 @@ msgid "This node has been deprecated. Use AnimationTree instead." msgstr "" #: scene/gui/color_picker.cpp +msgid "Pick a color from the screen." +msgstr "" + +#: scene/gui/color_picker.cpp #, fuzzy msgid "Raw Mode" msgstr "Raw-Läge" #: scene/gui/color_picker.cpp +msgid "Switch between hexadecimal and code values." +msgstr "" + +#: scene/gui/color_picker.cpp #, fuzzy -msgid "Add current color as a preset" +msgid "Add current color as a preset." msgstr "Lägg till nuvarande färg som en förinställning" #: scene/gui/dialogs.cpp @@ -10361,6 +10410,20 @@ msgid "Varyings can only be assigned in vertex function." msgstr "" #, fuzzy +#~ msgid "Warnings:" +#~ msgstr "Varning" + +#, fuzzy +#~ msgid "Font Size:" +#~ msgstr "Vy framifrÃ¥n" + +#~ msgid "Line:" +#~ msgstr "Rad:" + +#~ msgid "Col:" +#~ msgstr "Kolumn:" + +#, fuzzy #~ msgid "OrientedPathFollow only works when set as a child of a Path node." #~ msgstr "" #~ "PathFollow2D fungerar bara när den är satt som ett barn till en Path2D-" diff --git a/editor/translations/ta.po b/editor/translations/ta.po index a928d02019..f1011a2a42 100644 --- a/editor/translations/ta.po +++ b/editor/translations/ta.po @@ -541,20 +541,12 @@ msgstr "" msgid "Reset Zoom" msgstr "" -#: editor/code_editor.cpp -msgid "Warnings:" -msgstr "" - -#: editor/code_editor.cpp -msgid "Font Size:" -msgstr "" - -#: editor/code_editor.cpp -msgid "Line:" +#: editor/code_editor.cpp modules/mono/editor/mono_bottom_panel.cpp +msgid "Warnings" msgstr "" #: editor/code_editor.cpp -msgid "Col:" +msgid "Line and column numbers." msgstr "" #: editor/connections_dialog.cpp @@ -849,8 +841,8 @@ msgstr "" #: editor/dependency_editor.cpp editor/editor_audio_buses.cpp #: editor/editor_file_dialog.cpp editor/editor_node.cpp #: editor/filesystem_dock.cpp editor/plugins/item_list_editor_plugin.cpp -#: editor/project_export.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_dock.cpp +#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp +#: editor/project_settings_editor.cpp editor/scene_tree_dock.cpp msgid "Delete" msgstr "" @@ -1102,7 +1094,7 @@ msgid "Add Bus" msgstr "" #: editor/editor_audio_buses.cpp -msgid "Create a new Bus Layout." +msgid "Add a new Audio Bus to this layout." msgstr "" #: editor/editor_audio_buses.cpp editor/editor_properties.cpp @@ -1131,6 +1123,10 @@ msgstr "" msgid "Load the default Bus Layout." msgstr "" +#: editor/editor_audio_buses.cpp +msgid "Create a new Bus Layout." +msgstr "" + #: editor/editor_autoload_settings.cpp msgid "Invalid name." msgstr "" @@ -2301,7 +2297,7 @@ msgid "Save & Restart" msgstr "" #: editor/editor_node.cpp -msgid "Spins when the editor window repaints!" +msgid "Spins when the editor window redraws." msgstr "" #: editor/editor_node.cpp @@ -3340,37 +3336,37 @@ msgid "Create Polygon" msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Edit Polygon" +#: editor/plugins/animation_blend_space_1d_editor.cpp +#: editor/plugins/animation_blend_space_2d_editor.cpp +msgid "Create points." msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Insert Point" +msgid "" +"Edit points.\n" +"LMB: Move Point\n" +"RMB: Erase Point" msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Edit Polygon (Remove Point)" +#: editor/plugins/animation_blend_space_1d_editor.cpp +msgid "Erase points." msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Remove Polygon And Point" +msgid "Edit Polygon" msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -#: editor/plugins/animation_blend_space_1d_editor.cpp -#: editor/plugins/animation_blend_space_2d_editor.cpp -msgid "Create points." +msgid "Insert Point" msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "" -"Edit points.\n" -"LMB: Move Point\n" -"RMB: Erase Point" +msgid "Edit Polygon (Remove Point)" msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -#: editor/plugins/animation_blend_space_1d_editor.cpp -msgid "Erase points." +msgid "Remove Polygon And Point" msgstr "" #: editor/plugins/animation_blend_space_1d_editor.cpp @@ -4155,6 +4151,16 @@ msgid "Move CanvasItem" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp +msgid "Presets for the anchors and margins values of a Control node." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp +msgid "" +"Children of containers have their anchors and margins values overridden by " +"their parent." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp msgid "Anchors only" msgstr "" @@ -5051,6 +5057,12 @@ msgid "Create UV Map" msgstr "" #: editor/plugins/polygon_2d_editor_plugin.cpp +msgid "" +"Polygon 2D has internal vertices, so it can no longer be edited in the " +"viewport." +msgstr "" + +#: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Create Polygon & UV" msgstr "" @@ -6132,7 +6144,7 @@ msgid "Post" msgstr "" #: editor/plugins/spatial_editor_plugin.cpp -msgid "Name-less gizmo" +msgid "Nameless gizmo" msgstr "" #: editor/plugins/sprite_editor_plugin.cpp @@ -6208,7 +6220,12 @@ msgid "(empty)" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animations" +#, fuzzy +msgid "Animations:" +msgstr "மாறà¯à®±à®™à¯à®•ளை இதறà¯à®•௠அமை:" + +#: editor/plugins/sprite_frames_editor_plugin.cpp +msgid "New Animation" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp @@ -6220,7 +6237,7 @@ msgid "Loop" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animation Frames" +msgid "Animation Frames:" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp @@ -7001,6 +7018,19 @@ msgstr "" #: editor/project_manager.cpp msgid "" +"The following project settings file does not specify the version of Godot " +"through which it was created.\n" +"\n" +"%s\n" +"\n" +"If you proceed with opening it, it will be converted to Godot's current " +"configuration file format.\n" +"Warning: You will not be able to open the project with previous versions of " +"the engine anymore." +msgstr "" + +#: editor/project_manager.cpp +msgid "" "The following project settings file was generated by an older engine " "version, and needs to be converted for this version:\n" "\n" @@ -8481,10 +8511,6 @@ msgid "Build Project" msgstr "" #: modules/mono/editor/mono_bottom_panel.cpp -msgid "Warnings" -msgstr "" - -#: modules/mono/editor/mono_bottom_panel.cpp msgid "View log" msgstr "" @@ -9110,6 +9136,13 @@ msgid "" "ParallaxLayer node only works when set as child of a ParallaxBackground node." msgstr "" +#: scene/2d/particles_2d.cpp +msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles2D node instead. You can use the \"Convert to " +"CPUParticles\" option for this purpose." +msgstr "" + #: scene/2d/particles_2d.cpp scene/3d/particles.cpp msgid "" "A material to process the particles is not assigned, so no behavior is " @@ -9265,6 +9298,13 @@ msgstr "" #: scene/3d/particles.cpp msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles node instead. You can use the \"Convert to CPUParticles" +"\" option for this purpose." +msgstr "" + +#: scene/3d/particles.cpp +msgid "" "Nothing is visible because meshes have not been assigned to draw passes." msgstr "" @@ -9295,21 +9335,6 @@ msgstr "" msgid "Path property must point to a valid Spatial node to work." msgstr "" -#: scene/3d/scenario_fx.cpp -msgid "WorldEnvironment needs an Environment resource." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " -"this environment's Background Mode to Canvas (for 2D scenes)." -msgstr "" - #: scene/3d/soft_body.cpp msgid "This body will be ignored until you set a mesh" msgstr "" @@ -9333,6 +9358,21 @@ msgid "" "it as a child of a VehicleBody." msgstr "" +#: scene/3d/world_environment.cpp +msgid "WorldEnvironment needs an Environment resource." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " +"this environment's Background Mode to Canvas (for 2D scenes)." +msgstr "" + #: scene/animation/animation_blend_tree.cpp msgid "On BlendTree node '%s', animation not found: '%s'" msgstr "" @@ -9374,11 +9414,19 @@ msgid "This node has been deprecated. Use AnimationTree instead." msgstr "" #: scene/gui/color_picker.cpp +msgid "Pick a color from the screen." +msgstr "" + +#: scene/gui/color_picker.cpp msgid "Raw Mode" msgstr "" #: scene/gui/color_picker.cpp -msgid "Add current color as a preset" +msgid "Switch between hexadecimal and code values." +msgstr "" + +#: scene/gui/color_picker.cpp +msgid "Add current color as a preset." msgstr "" #: scene/gui/dialogs.cpp diff --git a/editor/translations/te.po b/editor/translations/te.po index 394a3c4208..ac7d358ee0 100644 --- a/editor/translations/te.po +++ b/editor/translations/te.po @@ -532,20 +532,12 @@ msgstr "" msgid "Reset Zoom" msgstr "" -#: editor/code_editor.cpp -msgid "Warnings:" -msgstr "" - -#: editor/code_editor.cpp -msgid "Font Size:" -msgstr "" - -#: editor/code_editor.cpp -msgid "Line:" +#: editor/code_editor.cpp modules/mono/editor/mono_bottom_panel.cpp +msgid "Warnings" msgstr "" #: editor/code_editor.cpp -msgid "Col:" +msgid "Line and column numbers." msgstr "" #: editor/connections_dialog.cpp @@ -839,8 +831,8 @@ msgstr "" #: editor/dependency_editor.cpp editor/editor_audio_buses.cpp #: editor/editor_file_dialog.cpp editor/editor_node.cpp #: editor/filesystem_dock.cpp editor/plugins/item_list_editor_plugin.cpp -#: editor/project_export.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_dock.cpp +#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp +#: editor/project_settings_editor.cpp editor/scene_tree_dock.cpp msgid "Delete" msgstr "" @@ -1092,7 +1084,7 @@ msgid "Add Bus" msgstr "" #: editor/editor_audio_buses.cpp -msgid "Create a new Bus Layout." +msgid "Add a new Audio Bus to this layout." msgstr "" #: editor/editor_audio_buses.cpp editor/editor_properties.cpp @@ -1121,6 +1113,10 @@ msgstr "" msgid "Load the default Bus Layout." msgstr "" +#: editor/editor_audio_buses.cpp +msgid "Create a new Bus Layout." +msgstr "" + #: editor/editor_autoload_settings.cpp msgid "Invalid name." msgstr "" @@ -2291,7 +2287,7 @@ msgid "Save & Restart" msgstr "" #: editor/editor_node.cpp -msgid "Spins when the editor window repaints!" +msgid "Spins when the editor window redraws." msgstr "" #: editor/editor_node.cpp @@ -3329,37 +3325,37 @@ msgid "Create Polygon" msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Edit Polygon" +#: editor/plugins/animation_blend_space_1d_editor.cpp +#: editor/plugins/animation_blend_space_2d_editor.cpp +msgid "Create points." msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Insert Point" +msgid "" +"Edit points.\n" +"LMB: Move Point\n" +"RMB: Erase Point" msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Edit Polygon (Remove Point)" +#: editor/plugins/animation_blend_space_1d_editor.cpp +msgid "Erase points." msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Remove Polygon And Point" +msgid "Edit Polygon" msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -#: editor/plugins/animation_blend_space_1d_editor.cpp -#: editor/plugins/animation_blend_space_2d_editor.cpp -msgid "Create points." +msgid "Insert Point" msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "" -"Edit points.\n" -"LMB: Move Point\n" -"RMB: Erase Point" +msgid "Edit Polygon (Remove Point)" msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp -#: editor/plugins/animation_blend_space_1d_editor.cpp -msgid "Erase points." +msgid "Remove Polygon And Point" msgstr "" #: editor/plugins/animation_blend_space_1d_editor.cpp @@ -4142,6 +4138,16 @@ msgid "Move CanvasItem" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp +msgid "Presets for the anchors and margins values of a Control node." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp +msgid "" +"Children of containers have their anchors and margins values overridden by " +"their parent." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp msgid "Anchors only" msgstr "" @@ -5037,6 +5043,12 @@ msgid "Create UV Map" msgstr "" #: editor/plugins/polygon_2d_editor_plugin.cpp +msgid "" +"Polygon 2D has internal vertices, so it can no longer be edited in the " +"viewport." +msgstr "" + +#: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Create Polygon & UV" msgstr "" @@ -6118,7 +6130,7 @@ msgid "Post" msgstr "" #: editor/plugins/spatial_editor_plugin.cpp -msgid "Name-less gizmo" +msgid "Nameless gizmo" msgstr "" #: editor/plugins/sprite_editor_plugin.cpp @@ -6194,7 +6206,11 @@ msgid "(empty)" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animations" +msgid "Animations:" +msgstr "" + +#: editor/plugins/sprite_frames_editor_plugin.cpp +msgid "New Animation" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp @@ -6206,7 +6222,7 @@ msgid "Loop" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animation Frames" +msgid "Animation Frames:" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp @@ -6982,6 +6998,19 @@ msgstr "" #: editor/project_manager.cpp msgid "" +"The following project settings file does not specify the version of Godot " +"through which it was created.\n" +"\n" +"%s\n" +"\n" +"If you proceed with opening it, it will be converted to Godot's current " +"configuration file format.\n" +"Warning: You will not be able to open the project with previous versions of " +"the engine anymore." +msgstr "" + +#: editor/project_manager.cpp +msgid "" "The following project settings file was generated by an older engine " "version, and needs to be converted for this version:\n" "\n" @@ -8458,10 +8487,6 @@ msgid "Build Project" msgstr "" #: modules/mono/editor/mono_bottom_panel.cpp -msgid "Warnings" -msgstr "" - -#: modules/mono/editor/mono_bottom_panel.cpp msgid "View log" msgstr "" @@ -9087,6 +9112,13 @@ msgid "" "ParallaxLayer node only works when set as child of a ParallaxBackground node." msgstr "" +#: scene/2d/particles_2d.cpp +msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles2D node instead. You can use the \"Convert to " +"CPUParticles\" option for this purpose." +msgstr "" + #: scene/2d/particles_2d.cpp scene/3d/particles.cpp msgid "" "A material to process the particles is not assigned, so no behavior is " @@ -9242,6 +9274,13 @@ msgstr "" #: scene/3d/particles.cpp msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles node instead. You can use the \"Convert to CPUParticles" +"\" option for this purpose." +msgstr "" + +#: scene/3d/particles.cpp +msgid "" "Nothing is visible because meshes have not been assigned to draw passes." msgstr "" @@ -9272,21 +9311,6 @@ msgstr "" msgid "Path property must point to a valid Spatial node to work." msgstr "" -#: scene/3d/scenario_fx.cpp -msgid "WorldEnvironment needs an Environment resource." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " -"this environment's Background Mode to Canvas (for 2D scenes)." -msgstr "" - #: scene/3d/soft_body.cpp msgid "This body will be ignored until you set a mesh" msgstr "" @@ -9310,6 +9334,21 @@ msgid "" "it as a child of a VehicleBody." msgstr "" +#: scene/3d/world_environment.cpp +msgid "WorldEnvironment needs an Environment resource." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " +"this environment's Background Mode to Canvas (for 2D scenes)." +msgstr "" + #: scene/animation/animation_blend_tree.cpp msgid "On BlendTree node '%s', animation not found: '%s'" msgstr "" @@ -9351,11 +9390,19 @@ msgid "This node has been deprecated. Use AnimationTree instead." msgstr "" #: scene/gui/color_picker.cpp +msgid "Pick a color from the screen." +msgstr "" + +#: scene/gui/color_picker.cpp msgid "Raw Mode" msgstr "" #: scene/gui/color_picker.cpp -msgid "Add current color as a preset" +msgid "Switch between hexadecimal and code values." +msgstr "" + +#: scene/gui/color_picker.cpp +msgid "Add current color as a preset." msgstr "" #: scene/gui/dialogs.cpp diff --git a/editor/translations/th.po b/editor/translations/th.po index afc0684350..62bf2f8594 100644 --- a/editor/translations/th.po +++ b/editor/translations/th.po @@ -567,23 +567,13 @@ msgstr "ย่à¸" msgid "Reset Zoom" msgstr "รีเซ็ตซูม" -#: editor/code_editor.cpp -#, fuzzy -msgid "Warnings:" +#: editor/code_editor.cpp modules/mono/editor/mono_bottom_panel.cpp +msgid "Warnings" msgstr "คำเตืà¸à¸™" #: editor/code_editor.cpp -#, fuzzy -msgid "Font Size:" -msgstr "ขนาดฟà¸à¸™à¸•์ต้นฉบับ:" - -#: editor/code_editor.cpp -msgid "Line:" -msgstr "บรรทัด:" - -#: editor/code_editor.cpp -msgid "Col:" -msgstr "คà¸à¸¥à¸±à¸¡à¸™à¹Œ:" +msgid "Line and column numbers." +msgstr "" #: editor/connections_dialog.cpp msgid "Method in target Node must be specified!" @@ -890,8 +880,8 @@ msgstr "ลบไฟล์ที่เลืà¸à¸?" #: editor/dependency_editor.cpp editor/editor_audio_buses.cpp #: editor/editor_file_dialog.cpp editor/editor_node.cpp #: editor/filesystem_dock.cpp editor/plugins/item_list_editor_plugin.cpp -#: editor/project_export.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_dock.cpp +#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp +#: editor/project_settings_editor.cpp editor/scene_tree_dock.cpp msgid "Delete" msgstr "ลบ" @@ -1147,8 +1137,9 @@ msgid "Add Bus" msgstr "เพิ่ม Bus" #: editor/editor_audio_buses.cpp -msgid "Create a new Bus Layout." -msgstr "สร้างเลย์เà¸à¸²à¸•์ Bus ใหม่" +#, fuzzy +msgid "Add a new Audio Bus to this layout." +msgstr "บันทึà¸à¹€à¸¥à¸¢à¹Œà¹€à¸à¸²à¸•์ขà¸à¸‡ Audio Bus เป็น..." #: editor/editor_audio_buses.cpp editor/editor_properties.cpp #: editor/plugins/animation_player_editor_plugin.cpp editor/property_editor.cpp @@ -1176,6 +1167,10 @@ msgstr "โหลดค่าเริ่มต้น" msgid "Load the default Bus Layout." msgstr "โหลดค่าเริ่มต้นเลย์เà¸à¸²à¸•์ Bus" +#: editor/editor_audio_buses.cpp +msgid "Create a new Bus Layout." +msgstr "สร้างเลย์เà¸à¸²à¸•์ Bus ใหม่" + #: editor/editor_autoload_settings.cpp msgid "Invalid name." msgstr "ชื่à¸à¸œà¸´à¸”พลาด" @@ -2410,7 +2405,8 @@ msgid "Save & Restart" msgstr "บันทึà¸à¹à¸¥à¸°à¸™à¸³à¹€à¸‚้าà¸à¸µà¸à¸„รั้ง" #: editor/editor_node.cpp -msgid "Spins when the editor window repaints!" +#, fuzzy +msgid "Spins when the editor window redraws." msgstr "หมุนเมื่à¸à¸¡à¸µà¸à¸²à¸£à¸§à¸²à¸”หน้าต่างโปรà¹à¸à¸£à¸¡à¹ƒà¸«à¸¡à¹ˆ!" #: editor/editor_node.cpp @@ -3501,25 +3497,6 @@ msgid "Create Polygon" msgstr "สร้างรูปหลายเหลี่ยม" #: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Edit Polygon" -msgstr "à¹à¸à¹‰à¹„ขรูปหลายเหลี่ยม" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Insert Point" -msgstr "à¹à¸—รà¸à¸ˆà¸¸à¸”" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Edit Polygon (Remove Point)" -msgstr "à¹à¸à¹‰à¹„ขรูปหลายเหลี่ยม (ลบจุด)" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Remove Polygon And Point" -msgstr "ลบรูปหลายเหลี่ยมà¹à¸¥à¸°à¸ˆà¸¸à¸”" - -#: editor/plugins/abstract_polygon_2d_editor.cpp #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #, fuzzy @@ -3544,6 +3521,25 @@ msgstr "" msgid "Erase points." msgstr "คลิà¸à¸‚วา: ลบจุด" +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Edit Polygon" +msgstr "à¹à¸à¹‰à¹„ขรูปหลายเหลี่ยม" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Insert Point" +msgstr "à¹à¸—รà¸à¸ˆà¸¸à¸”" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Edit Polygon (Remove Point)" +msgstr "à¹à¸à¹‰à¹„ขรูปหลายเหลี่ยม (ลบจุด)" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Remove Polygon And Point" +msgstr "ลบรูปหลายเหลี่ยมà¹à¸¥à¸°à¸ˆà¸¸à¸”" + #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #: editor/plugins/animation_player_editor_plugin.cpp @@ -4359,6 +4355,16 @@ msgid "Move CanvasItem" msgstr "à¹à¸à¹‰à¹„ข CanvasItem" #: editor/plugins/canvas_item_editor_plugin.cpp +msgid "Presets for the anchors and margins values of a Control node." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp +msgid "" +"Children of containers have their anchors and margins values overridden by " +"their parent." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp msgid "Anchors only" msgstr "ปรับหมุดเท่านั้น" @@ -5276,6 +5282,12 @@ msgid "Create UV Map" msgstr "สร้าง UV Map" #: editor/plugins/polygon_2d_editor_plugin.cpp +msgid "" +"Polygon 2D has internal vertices, so it can no longer be edited in the " +"viewport." +msgstr "" + +#: editor/plugins/polygon_2d_editor_plugin.cpp #, fuzzy msgid "Create Polygon & UV" msgstr "สร้างรูปหลายเหลี่ยม" @@ -6416,7 +6428,7 @@ msgid "Post" msgstr "หลัง" #: editor/plugins/spatial_editor_plugin.cpp -msgid "Name-less gizmo" +msgid "Nameless gizmo" msgstr "" #: editor/plugins/sprite_editor_plugin.cpp @@ -6499,7 +6511,13 @@ msgid "(empty)" msgstr "(ว่างเปล่า)" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animations" +#, fuzzy +msgid "Animations:" +msgstr "à¹à¸à¸™à¸´à¹€à¸¡à¸Šà¸±à¸™" + +#: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "New Animation" msgstr "à¹à¸à¸™à¸´à¹€à¸¡à¸Šà¸±à¸™" #: editor/plugins/sprite_frames_editor_plugin.cpp @@ -6511,7 +6529,8 @@ msgid "Loop" msgstr "วน" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animation Frames" +#, fuzzy +msgid "Animation Frames:" msgstr "เฟรมà¹à¸à¸™à¸´à¹€à¸¡à¸Šà¸±à¸™" #: editor/plugins/sprite_frames_editor_plugin.cpp @@ -7348,6 +7367,19 @@ msgstr "ยืนยันà¸à¸²à¸£à¹€à¸›à¸´à¸”โปรเจà¸à¸•์มาภ#: editor/project_manager.cpp msgid "" +"The following project settings file does not specify the version of Godot " +"through which it was created.\n" +"\n" +"%s\n" +"\n" +"If you proceed with opening it, it will be converted to Godot's current " +"configuration file format.\n" +"Warning: You will not be able to open the project with previous versions of " +"the engine anymore." +msgstr "" + +#: editor/project_manager.cpp +msgid "" "The following project settings file was generated by an older engine " "version, and needs to be converted for this version:\n" "\n" @@ -8888,10 +8920,6 @@ msgid "Build Project" msgstr "Build โปรเจà¸à¸•์" #: modules/mono/editor/mono_bottom_panel.cpp -msgid "Warnings" -msgstr "คำเตืà¸à¸™" - -#: modules/mono/editor/mono_bottom_panel.cpp #, fuzzy msgid "View log" msgstr "ดูไฟล์" @@ -9541,6 +9569,13 @@ msgid "" "ParallaxLayer node only works when set as child of a ParallaxBackground node." msgstr "ParallaxLayer จะทำงานได้ต้à¸à¸‡à¹€à¸›à¹‡à¸™à¹‚หนดลูà¸à¸‚à¸à¸‡à¹‚หนด ParallaxBackground" +#: scene/2d/particles_2d.cpp +msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles2D node instead. You can use the \"Convert to " +"CPUParticles\" option for this purpose." +msgstr "" + #: scene/2d/particles_2d.cpp scene/3d/particles.cpp msgid "" "A material to process the particles is not assigned, so no behavior is " @@ -9708,6 +9743,13 @@ msgstr "" #: scene/3d/particles.cpp msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles node instead. You can use the \"Convert to CPUParticles" +"\" option for this purpose." +msgstr "" + +#: scene/3d/particles.cpp +msgid "" "Nothing is visible because meshes have not been assigned to draw passes." msgstr "ไม่มีà¸à¸²à¸£à¹à¸ªà¸”งผลเนื่à¸à¸‡à¸ˆà¸²à¸à¹„ม่ได้à¸à¸³à¸«à¸™à¸” mesh ใน draw pass" @@ -9741,21 +9783,6 @@ msgstr "" msgid "Path property must point to a valid Spatial node to work." msgstr "ต้à¸à¸‡à¹à¸à¹‰à¹„ข Path ให้ชี้ไปยังโหนด Spatial จึงจะทำงานได้" -#: scene/3d/scenario_fx.cpp -msgid "WorldEnvironment needs an Environment resource." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." -msgstr "จะมี WorldEnvironment ได้เพียงโหนดเดียวในฉาภ(หรืà¸à¸à¸¥à¸¸à¹ˆà¸¡à¸‚à¸à¸‡à¸‰à¸²à¸à¸—ี่เป็นà¸à¸´à¸™à¸ªà¹à¸•นซ์)" - -#: scene/3d/scenario_fx.cpp -msgid "" -"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " -"this environment's Background Mode to Canvas (for 2D scenes)." -msgstr "" - #: scene/3d/soft_body.cpp msgid "This body will be ignored until you set a mesh" msgstr "" @@ -9782,6 +9809,21 @@ msgid "" "it as a child of a VehicleBody." msgstr "VehicleWheel เป็นระบบล้à¸à¸‚à¸à¸‡ VehicleBody à¸à¸£à¸¸à¸“าใช้เป็นโหนดลูà¸à¸‚à¸à¸‡ VehicleBody" +#: scene/3d/world_environment.cpp +msgid "WorldEnvironment needs an Environment resource." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." +msgstr "จะมี WorldEnvironment ได้เพียงโหนดเดียวในฉาภ(หรืà¸à¸à¸¥à¸¸à¹ˆà¸¡à¸‚à¸à¸‡à¸‰à¸²à¸à¸—ี่เป็นà¸à¸´à¸™à¸ªà¹à¸•นซ์)" + +#: scene/3d/world_environment.cpp +msgid "" +"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " +"this environment's Background Mode to Canvas (for 2D scenes)." +msgstr "" + #: scene/animation/animation_blend_tree.cpp msgid "On BlendTree node '%s', animation not found: '%s'" msgstr "" @@ -9828,11 +9870,20 @@ msgid "This node has been deprecated. Use AnimationTree instead." msgstr "" #: scene/gui/color_picker.cpp +msgid "Pick a color from the screen." +msgstr "" + +#: scene/gui/color_picker.cpp msgid "Raw Mode" msgstr "โหมด Raw" #: scene/gui/color_picker.cpp -msgid "Add current color as a preset" +msgid "Switch between hexadecimal and code values." +msgstr "" + +#: scene/gui/color_picker.cpp +#, fuzzy +msgid "Add current color as a preset." msgstr "เพิ่มสีที่เลืà¸à¸à¹ƒà¸™à¸£à¸²à¸¢à¸à¸²à¸£à¹‚ปรด" #: scene/gui/dialogs.cpp @@ -9928,6 +9979,20 @@ msgid "Varyings can only be assigned in vertex function." msgstr "" #, fuzzy +#~ msgid "Warnings:" +#~ msgstr "คำเตืà¸à¸™" + +#, fuzzy +#~ msgid "Font Size:" +#~ msgstr "ขนาดฟà¸à¸™à¸•์ต้นฉบับ:" + +#~ msgid "Line:" +#~ msgstr "บรรทัด:" + +#~ msgid "Col:" +#~ msgstr "คà¸à¸¥à¸±à¸¡à¸™à¹Œ:" + +#, fuzzy #~ msgid "OrientedPathFollow only works when set as a child of a Path node." #~ msgstr "PathFollow2D จะทำงานได้ต้à¸à¸‡à¹€à¸›à¹‡à¸™à¹‚หนดลูà¸à¸‚à¸à¸‡à¹‚หนด Path2D" diff --git a/editor/translations/tr.po b/editor/translations/tr.po index 1f52b34675..ccb0acce73 100644 --- a/editor/translations/tr.po +++ b/editor/translations/tr.po @@ -20,12 +20,13 @@ # Onur Sanır <onursanir@gmail.com>, 2018. # OÄŸuzhan Özdemir <ozdemiroguzhan0@gmail.com>, 2018. # Alper Çitmen <alper.citmen@gmail.com>, 2019. +# ege1212 <owlphp@gmail.com>, 2019. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2019-01-19 19:22+0000\n" -"Last-Translator: Alper Çitmen <alper.citmen@gmail.com>\n" +"PO-Revision-Date: 2019-02-13 07:10+0000\n" +"Last-Translator: ege1212 <owlphp@gmail.com>\n" "Language-Team: Turkish <https://hosted.weblate.org/projects/godot-engine/" "godot/tr/>\n" "Language: tr\n" @@ -33,7 +34,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 3.4-dev\n" +"X-Generator: Weblate 3.5-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -49,7 +50,7 @@ msgstr "Byte kodu çözmek için yetersiz byte, ya da Geçersiz format." #: core/math/expression.cpp msgid "Invalid input %i (not passed) in expression" -msgstr "" +msgstr "Geçersiz girdi, ifadede %i (geçirilmedi)" #: core/math/expression.cpp msgid "self can't be used because instance is null (not passed)" @@ -582,23 +583,13 @@ msgstr "UzaklaÅŸtır" msgid "Reset Zoom" msgstr "YaklaÅŸmayı Sıfırla" -#: editor/code_editor.cpp -#, fuzzy -msgid "Warnings:" +#: editor/code_editor.cpp modules/mono/editor/mono_bottom_panel.cpp +msgid "Warnings" msgstr "Uyarılar" #: editor/code_editor.cpp -#, fuzzy -msgid "Font Size:" -msgstr "Kaynak Yazı Türü Boyutu:" - -#: editor/code_editor.cpp -msgid "Line:" -msgstr "Satır:" - -#: editor/code_editor.cpp -msgid "Col:" -msgstr "Sütun:" +msgid "Line and column numbers." +msgstr "" #: editor/connections_dialog.cpp msgid "Method in target Node must be specified!" @@ -907,8 +898,8 @@ msgstr "Seçili dosyalar silinsin mi?" #: editor/dependency_editor.cpp editor/editor_audio_buses.cpp #: editor/editor_file_dialog.cpp editor/editor_node.cpp #: editor/filesystem_dock.cpp editor/plugins/item_list_editor_plugin.cpp -#: editor/project_export.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_dock.cpp +#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp +#: editor/project_settings_editor.cpp editor/scene_tree_dock.cpp msgid "Delete" msgstr "Sil" @@ -1165,8 +1156,9 @@ msgid "Add Bus" msgstr "Bus ekle" #: editor/editor_audio_buses.cpp -msgid "Create a new Bus Layout." -msgstr "Yeni bir Bus YerleÅŸim Düzeni oluÅŸtur." +#, fuzzy +msgid "Add a new Audio Bus to this layout." +msgstr "Audio Bus YerleÅŸim Düzenini Farklı Kaydet..." #: editor/editor_audio_buses.cpp editor/editor_properties.cpp #: editor/plugins/animation_player_editor_plugin.cpp editor/property_editor.cpp @@ -1194,6 +1186,10 @@ msgstr "Varsayılanı Yükle" msgid "Load the default Bus Layout." msgstr "Varsayılan Bus YerleÅŸim Düzenini Yükle." +#: editor/editor_audio_buses.cpp +msgid "Create a new Bus Layout." +msgstr "Yeni bir Bus YerleÅŸim Düzeni oluÅŸtur." + #: editor/editor_autoload_settings.cpp msgid "Invalid name." msgstr "Geçersiz ad." @@ -2463,7 +2459,8 @@ msgid "Save & Restart" msgstr "Kaydet & Yeniden İçe Aktar" #: editor/editor_node.cpp -msgid "Spins when the editor window repaints!" +#, fuzzy +msgid "Spins when the editor window redraws." msgstr "Düzenleyici penceresi yeniden boyandığında döndürülür!" #: editor/editor_node.cpp @@ -3562,25 +3559,6 @@ msgid "Create Polygon" msgstr "Çoklu OluÅŸturun" #: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Edit Polygon" -msgstr "Çokluyu Düzenleyin" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Insert Point" -msgstr "Nokta YerleÅŸtir" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Edit Polygon (Remove Point)" -msgstr "Çokluyu Düzenleyin (Noktayı Silin)" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Remove Polygon And Point" -msgstr "Çokluyu ve Noktayı Kaldır" - -#: editor/plugins/abstract_polygon_2d_editor.cpp #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #, fuzzy @@ -3605,6 +3583,25 @@ msgstr "" msgid "Erase points." msgstr "RMB: Noktayı Sil." +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Edit Polygon" +msgstr "Çokluyu Düzenleyin" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Insert Point" +msgstr "Nokta YerleÅŸtir" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Edit Polygon (Remove Point)" +msgstr "Çokluyu Düzenleyin (Noktayı Silin)" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Remove Polygon And Point" +msgstr "Çokluyu ve Noktayı Kaldır" + #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #: editor/plugins/animation_player_editor_plugin.cpp @@ -4424,6 +4421,16 @@ msgid "Move CanvasItem" msgstr "CanvasItem Düzenle" #: editor/plugins/canvas_item_editor_plugin.cpp +msgid "Presets for the anchors and margins values of a Control node." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp +msgid "" +"Children of containers have their anchors and margins values overridden by " +"their parent." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp msgid "Anchors only" msgstr "Sadece çapalar" @@ -5341,6 +5348,12 @@ msgid "Create UV Map" msgstr "UV Haritası OluÅŸtur" #: editor/plugins/polygon_2d_editor_plugin.cpp +msgid "" +"Polygon 2D has internal vertices, so it can no longer be edited in the " +"viewport." +msgstr "" + +#: editor/plugins/polygon_2d_editor_plugin.cpp #, fuzzy msgid "Create Polygon & UV" msgstr "Çoklu OluÅŸturun" @@ -6481,7 +6494,7 @@ msgid "Post" msgstr "Sonrası" #: editor/plugins/spatial_editor_plugin.cpp -msgid "Name-less gizmo" +msgid "Nameless gizmo" msgstr "" #: editor/plugins/sprite_editor_plugin.cpp @@ -6564,10 +6577,16 @@ msgid "(empty)" msgstr "(boÅŸ)" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animations" +#, fuzzy +msgid "Animations:" msgstr "Animasyonlar" #: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "New Animation" +msgstr "Animasyon" + +#: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed (FPS):" msgstr "Hız (FPS):" @@ -6576,7 +6595,8 @@ msgid "Loop" msgstr "Döngü" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animation Frames" +#, fuzzy +msgid "Animation Frames:" msgstr "Animasyon Çerçeveleri" #: editor/plugins/sprite_frames_editor_plugin.cpp @@ -7414,6 +7434,19 @@ msgstr "Birden fazla proje açmakta kararlı mısınız?" #: editor/project_manager.cpp msgid "" +"The following project settings file does not specify the version of Godot " +"through which it was created.\n" +"\n" +"%s\n" +"\n" +"If you proceed with opening it, it will be converted to Godot's current " +"configuration file format.\n" +"Warning: You will not be able to open the project with previous versions of " +"the engine anymore." +msgstr "" + +#: editor/project_manager.cpp +msgid "" "The following project settings file was generated by an older engine " "version, and needs to be converted for this version:\n" "\n" @@ -8964,10 +8997,6 @@ msgid "Build Project" msgstr "Projeyi İnÅŸa et" #: modules/mono/editor/mono_bottom_panel.cpp -msgid "Warnings" -msgstr "Uyarılar" - -#: modules/mono/editor/mono_bottom_panel.cpp #, fuzzy msgid "View log" msgstr "Dosyaları Görüntüle" @@ -9642,6 +9671,13 @@ msgstr "" "ParallaxLayer, yalnızca ParallaxBackground düğümünün çocuÄŸu olduÄŸu zaman " "çalışır." +#: scene/2d/particles_2d.cpp +msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles2D node instead. You can use the \"Convert to " +"CPUParticles\" option for this purpose." +msgstr "" + #: scene/2d/particles_2d.cpp scene/3d/particles.cpp msgid "" "A material to process the particles is not assigned, so no behavior is " @@ -9828,6 +9864,13 @@ msgstr "" #: scene/3d/particles.cpp msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles node instead. You can use the \"Convert to CPUParticles" +"\" option for this purpose." +msgstr "" + +#: scene/3d/particles.cpp +msgid "" "Nothing is visible because meshes have not been assigned to draw passes." msgstr "" "HiçbirÅŸey görünebilir deÄŸil çünkü örüntüler çizim geçiÅŸlerine atanmış deÄŸil." @@ -9865,25 +9908,6 @@ msgid "Path property must point to a valid Spatial node to work." msgstr "" "Yol özelliÄŸi, çalışmak için geçerli bir Spatial düğümüne iÅŸaret etmelidir." -#: scene/3d/scenario_fx.cpp -msgid "WorldEnvironment needs an Environment resource." -msgstr "WorldEnvironment bir Environment kaynağı gerektirir." - -#: scene/3d/scenario_fx.cpp -msgid "" -"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." -msgstr "" -"Her sahne başına (ya da örneklenmiÅŸ sahneler dizisine) sadece bir tane " -"WorldEnvironment 'a izin verilir." - -#: scene/3d/scenario_fx.cpp -msgid "" -"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " -"this environment's Background Mode to Canvas (for 2D scenes)." -msgstr "" -"Bu WorldEnvironment yoksayıldı. (3B sahneler için) Bir Kamera ekleyin veya " -"(2B sahneler için) bu ortamın Arkaplan Kipini Canvas olarak ayarlayın." - #: scene/3d/soft_body.cpp msgid "This body will be ignored until you set a mesh" msgstr "" @@ -9915,6 +9939,25 @@ msgstr "" "VehicleWheel VehicleBody'ye bir tekerlek sistemi saÄŸlaması için hizmet eder. " "Lütfen bunu VehicleBody'nin çocuÄŸu olarak kullanın." +#: scene/3d/world_environment.cpp +msgid "WorldEnvironment needs an Environment resource." +msgstr "WorldEnvironment bir Environment kaynağı gerektirir." + +#: scene/3d/world_environment.cpp +msgid "" +"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." +msgstr "" +"Her sahne başına (ya da örneklenmiÅŸ sahneler dizisine) sadece bir tane " +"WorldEnvironment 'a izin verilir." + +#: scene/3d/world_environment.cpp +msgid "" +"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " +"this environment's Background Mode to Canvas (for 2D scenes)." +msgstr "" +"Bu WorldEnvironment yoksayıldı. (3B sahneler için) Bir Kamera ekleyin veya " +"(2B sahneler için) bu ortamın Arkaplan Kipini Canvas olarak ayarlayın." + #: scene/animation/animation_blend_tree.cpp msgid "On BlendTree node '%s', animation not found: '%s'" msgstr "" @@ -9963,11 +10006,20 @@ msgid "This node has been deprecated. Use AnimationTree instead." msgstr "" #: scene/gui/color_picker.cpp +msgid "Pick a color from the screen." +msgstr "" + +#: scene/gui/color_picker.cpp msgid "Raw Mode" msgstr "Ham Kip" #: scene/gui/color_picker.cpp -msgid "Add current color as a preset" +msgid "Switch between hexadecimal and code values." +msgstr "" + +#: scene/gui/color_picker.cpp +#, fuzzy +msgid "Add current color as a preset." msgstr "Åžuanki rengi bir önayar olarak kaydet" #: scene/gui/dialogs.cpp @@ -10065,6 +10117,20 @@ msgid "Varyings can only be assigned in vertex function." msgstr "" #, fuzzy +#~ msgid "Warnings:" +#~ msgstr "Uyarılar" + +#, fuzzy +#~ msgid "Font Size:" +#~ msgstr "Kaynak Yazı Türü Boyutu:" + +#~ msgid "Line:" +#~ msgstr "Satır:" + +#~ msgid "Col:" +#~ msgstr "Sütun:" + +#, fuzzy #~ msgid "OrientedPathFollow only works when set as a child of a Path node." #~ msgstr "" #~ "PathFollow2D yalnızca Path2D düğümünün çocuÄŸu olarak ayarlanınca çalışır." diff --git a/editor/translations/uk.po b/editor/translations/uk.po index 84bf261ae2..f617cf3fc4 100644 --- a/editor/translations/uk.po +++ b/editor/translations/uk.po @@ -15,7 +15,7 @@ msgid "" msgstr "" "Project-Id-Version: Ukrainian (Godot Engine)\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2019-01-26 21:22+0000\n" +"PO-Revision-Date: 2019-02-13 07:10+0000\n" "Last-Translator: Yuri Chornoivan <yurchor@ukr.net>\n" "Language-Team: Ukrainian <https://hosted.weblate.org/projects/godot-engine/" "godot/uk/>\n" @@ -552,21 +552,14 @@ msgstr "ЗменшеннÑ" msgid "Reset Zoom" msgstr "Скинути маÑштаб" -#: editor/code_editor.cpp -msgid "Warnings:" -msgstr "ПопередженнÑ:" - -#: editor/code_editor.cpp -msgid "Font Size:" -msgstr "Розмір шрифту:" - -#: editor/code_editor.cpp -msgid "Line:" -msgstr "Ð Ñдок:" +#: editor/code_editor.cpp modules/mono/editor/mono_bottom_panel.cpp +msgid "Warnings" +msgstr "ПопередженнÑ" #: editor/code_editor.cpp -msgid "Col:" -msgstr "Колонка:" +#, fuzzy +msgid "Line and column numbers." +msgstr "Ðомери Ñ€Ñдків Ñ– позицій" #: editor/connections_dialog.cpp msgid "Method in target Node must be specified!" @@ -868,8 +861,8 @@ msgstr "Видалити вибрані файли?" #: editor/dependency_editor.cpp editor/editor_audio_buses.cpp #: editor/editor_file_dialog.cpp editor/editor_node.cpp #: editor/filesystem_dock.cpp editor/plugins/item_list_editor_plugin.cpp -#: editor/project_export.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_dock.cpp +#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp +#: editor/project_settings_editor.cpp editor/scene_tree_dock.cpp msgid "Delete" msgstr "Вилучити" @@ -1125,8 +1118,9 @@ msgid "Add Bus" msgstr "Додати шину" #: editor/editor_audio_buses.cpp -msgid "Create a new Bus Layout." -msgstr "Ð¡Ñ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð½Ð¾Ð²Ð¾Ð³Ð¾ ÐºÐ¾Ð¼Ð¿Ð¾Ð½ÑƒÐ²Ð°Ð½Ð½Ñ ÑˆÐ¸Ð½Ð¸." +#, fuzzy +msgid "Add a new Audio Bus to this layout." +msgstr "Зберегти ÐºÐ¾Ð¼Ð¿Ð¾Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð°ÑƒÐ´Ñ–Ð¾ шини Ñк..." #: editor/editor_audio_buses.cpp editor/editor_properties.cpp #: editor/plugins/animation_player_editor_plugin.cpp editor/property_editor.cpp @@ -1154,6 +1148,10 @@ msgstr "Завантажити типовий" msgid "Load the default Bus Layout." msgstr "Завантажити типове ÐºÐ¾Ð¼Ð¿Ð¾Ð½ÑƒÐ²Ð°Ð½Ð½Ñ ÑˆÐ¸Ð½Ð¸." +#: editor/editor_audio_buses.cpp +msgid "Create a new Bus Layout." +msgstr "Ð¡Ñ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð½Ð¾Ð²Ð¾Ð³Ð¾ ÐºÐ¾Ð¼Ð¿Ð¾Ð½ÑƒÐ²Ð°Ð½Ð½Ñ ÑˆÐ¸Ð½Ð¸." + #: editor/editor_autoload_settings.cpp msgid "Invalid name." msgstr "Ðекоректна назва." @@ -2400,7 +2398,8 @@ msgid "Save & Restart" msgstr "Зберегти Ñ– перезапуÑтити" #: editor/editor_node.cpp -msgid "Spins when the editor window repaints!" +#, fuzzy +msgid "Spins when the editor window redraws." msgstr "ОбертаєтьÑÑ, коли перемальовуєтьÑÑ Ð²Ñ–ÐºÐ½Ð¾ редактора!" #: editor/editor_node.cpp @@ -3326,17 +3325,18 @@ msgstr "Переімпортувати" #: editor/import_dock.cpp msgid "Save scenes, re-import and restart" -msgstr "" +msgstr "Зберегти Ñцени, повторно імпортувати Ñ– перезапуÑтити" #: editor/import_dock.cpp -#, fuzzy msgid "Changing the type of an imported file requires editor restart." -msgstr "Зміна відеодрайвера потребує перезапуÑку редактора." +msgstr "Зміна типу імпортованого файла потребує перезапуÑку редактора." #: editor/import_dock.cpp msgid "" "WARNING: Assets exist that use this resource, they may stop loading properly." msgstr "" +"Увага: Ñ–Ñують об'єкти, Ñкі викориÑтовують цей реÑурÑ, — вони можуть " +"припинити завантажуватиÑÑ Ð½Ð°Ð»ÐµÐ¶Ð½Ð¸Ð¼ чином." #: editor/inspector_dock.cpp msgid "Failed to load resource." @@ -3461,22 +3461,6 @@ msgid "Create Polygon" msgstr "Створити полігон" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Edit Polygon" -msgstr "Редагувати полігон" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Insert Point" -msgstr "Ð’Ñтавити точку" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Edit Polygon (Remove Point)" -msgstr "Редагувати полігон (вилучити точку)" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Remove Polygon And Point" -msgstr "Вилучити полігон та точку" - -#: editor/plugins/abstract_polygon_2d_editor.cpp #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp msgid "Create points." @@ -3497,6 +3481,22 @@ msgstr "" msgid "Erase points." msgstr "Витерти точки." +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Edit Polygon" +msgstr "Редагувати полігон" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Insert Point" +msgstr "Ð’Ñтавити точку" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Edit Polygon (Remove Point)" +msgstr "Редагувати полігон (вилучити точку)" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Remove Polygon And Point" +msgstr "Вилучити полігон та точку" + #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #: editor/plugins/animation_player_editor_plugin.cpp @@ -4304,6 +4304,18 @@ msgid "Move CanvasItem" msgstr "ПереÑунути CanvasItem" #: editor/plugins/canvas_item_editor_plugin.cpp +msgid "Presets for the anchors and margins values of a Control node." +msgstr "Шаблони Ð´Ð»Ñ Ð¿Ñ€Ð¸Ð²'Ñзок та Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð¿Ð¾Ð»Ñ–Ð² вузла керуваннÑ." + +#: editor/plugins/canvas_item_editor_plugin.cpp +msgid "" +"Children of containers have their anchors and margins values overridden by " +"their parent." +msgstr "" +"Дані щодо прив'Ñзок та значень полів дочірніх об'єктів перевизначаютьÑÑ " +"їхніми батьківÑькими об'єктами." + +#: editor/plugins/canvas_item_editor_plugin.cpp msgid "Anchors only" msgstr "Тільки прив'Ñзки" @@ -5211,6 +5223,12 @@ msgid "Create UV Map" msgstr "Створити UV-карту" #: editor/plugins/polygon_2d_editor_plugin.cpp +msgid "" +"Polygon 2D has internal vertices, so it can no longer be edited in the " +"viewport." +msgstr "" + +#: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Create Polygon & UV" msgstr "Створити полігон Ñ– UV" @@ -6300,7 +6318,7 @@ msgid "Post" msgstr "ПіÑлÑ" #: editor/plugins/spatial_editor_plugin.cpp -msgid "Name-less gizmo" +msgid "Nameless gizmo" msgstr "Штука без назви" #: editor/plugins/sprite_editor_plugin.cpp @@ -6378,8 +6396,12 @@ msgid "(empty)" msgstr "(порожньо)" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animations" -msgstr "Ðнімації" +msgid "Animations:" +msgstr "Ðнімації:" + +#: editor/plugins/sprite_frames_editor_plugin.cpp +msgid "New Animation" +msgstr "Ðова анімаціÑ" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed (FPS):" @@ -6390,8 +6412,8 @@ msgid "Loop" msgstr "Зациклити" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animation Frames" -msgstr "Кадри анімації" +msgid "Animation Frames:" +msgstr "Кадри анімації:" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Insert Empty (Before)" @@ -7148,11 +7170,11 @@ msgstr "Вибрати" #: editor/project_manager.cpp msgid "Renderer:" -msgstr "" +msgstr "Обробник:" #: editor/project_manager.cpp msgid "OpenGL ES 3.0" -msgstr "" +msgstr "OpenGL ES 3.0" #: editor/project_manager.cpp msgid "" @@ -7161,10 +7183,14 @@ msgid "" "Incompatible with older hardware\n" "Not recommended for web games" msgstr "" +"ВиÑока ÑкіÑть зображеннÑ\n" +"ДоÑтупні уÑÑ– можливоÑті\n" +"ÐеÑуміÑний із заÑтарілим обладнаннÑм\n" +"Ðе рекомендовано Ð´Ð»Ñ Ñ–Ð½Ñ‚ÐµÑ€Ð½ÐµÑ‚-ігор" #: editor/project_manager.cpp msgid "OpenGL ES 2.0" -msgstr "" +msgstr "OpenGL ES 2.0" #: editor/project_manager.cpp msgid "" @@ -7173,10 +7199,16 @@ msgid "" "Works on most hardware\n" "Recommended for web games" msgstr "" +"Ðижча ÑкіÑть зображеннÑ\n" +"ДеÑкі можливоÑті Ñ” недоÑтупними\n" +"Працює майже вÑюди\n" +"Рекомендовано Ð´Ð»Ñ Ñ–Ð½Ñ‚ÐµÑ€Ð½ÐµÑ‚-ігор" #: editor/project_manager.cpp msgid "Renderer can be changed later, but scenes may need to be adjusted." msgstr "" +"Обробник можна змінити пізніше, але, можливо, виникне потреба у коригуванні " +"Ñцен." #: editor/project_manager.cpp msgid "Unnamed Project" @@ -7192,6 +7224,28 @@ msgstr "Ви Ñправді хочете відкрити декілька прР#: editor/project_manager.cpp msgid "" +"The following project settings file does not specify the version of Godot " +"through which it was created.\n" +"\n" +"%s\n" +"\n" +"If you proceed with opening it, it will be converted to Godot's current " +"configuration file format.\n" +"Warning: You will not be able to open the project with previous versions of " +"the engine anymore." +msgstr "" +"У вказаному нижче файлі параметрів проекту не вказано верÑÑ–ÑŽ Godot, за " +"допомогою Ñкої його було Ñтворено.\n" +"\n" +"%s\n" +"\n" +"Якщо ви продовжите процедуру його відкриттÑ, дані буде перетворено до " +"формату файла налаштувань поточної верÑÑ–Ñ— Godot.\n" +"ПопередженнÑ: у результаті Ð¿ÐµÑ€ÐµÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð²Ð¸ втратите можливіÑть Ð²Ñ–Ð´ÐºÑ€Ð¸Ñ‚Ñ‚Ñ " +"проекту у заÑтарілих верÑÑ–ÑÑ… рушіÑ." + +#: editor/project_manager.cpp +msgid "" "The following project settings file was generated by an older engine " "version, and needs to be converted for this version:\n" "\n" @@ -7907,6 +7961,8 @@ msgstr "Дублювати вузли" #: editor/scene_tree_dock.cpp msgid "Can't reparent nodes in inherited scenes, order of nodes can't change." msgstr "" +"Ðе можна змінювати батьківÑький об'єкт вузлів в уÑпадкованих Ñценах — " +"порÑдок вузлів не можна змінювати." #: editor/scene_tree_dock.cpp msgid "Node must belong to the edited scene to become root." @@ -8723,10 +8779,6 @@ msgid "Build Project" msgstr "Зібрати проект" #: modules/mono/editor/mono_bottom_panel.cpp -msgid "Warnings" -msgstr "ПопередженнÑ" - -#: modules/mono/editor/mono_bottom_panel.cpp msgid "View log" msgstr "ПереглÑнути журнал" @@ -9411,6 +9463,17 @@ msgstr "" "Вузол ParallaxLayer працює, лише Ñкщо його вÑтановлено Ñк дочірній Ð´Ð»Ñ Ð²ÑƒÐ·Ð»Ð° " "ParallaxBackground." +#: scene/2d/particles_2d.cpp +msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles2D node instead. You can use the \"Convert to " +"CPUParticles\" option for this purpose." +msgstr "" +"У драйвері GLES2 не передбачено підтримки чаÑток із обробкою за допомогою " +"графічного процеÑора.\n" +"Вам Ñлід ÑкориÑтатиÑÑ Ð²ÑƒÐ·Ð»Ð¾Ð¼ CPUParticles2D. Ð”Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ можете вибрати пункт " +"«Перетворити на CPUParticles»." + #: scene/2d/particles_2d.cpp scene/3d/particles.cpp msgid "" "A material to process the particles is not assigned, so no behavior is " @@ -9601,6 +9664,17 @@ msgstr "" #: scene/3d/particles.cpp msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles node instead. You can use the \"Convert to CPUParticles" +"\" option for this purpose." +msgstr "" +"У драйвері GLES2 не передбачено підтримки чаÑток із обробкою за допомогою " +"графічного процеÑора.\n" +"Вам Ñлід ÑкориÑтатиÑÑ Ð²ÑƒÐ·Ð»Ð¾Ð¼ CPUParticles. Ð”Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ можете вибрати пункт " +"«Перетворити на CPUParticles»." + +#: scene/3d/particles.cpp +msgid "" "Nothing is visible because meshes have not been assigned to draw passes." msgstr "" "Ðічого не видно, оÑкільки Ñітки не було пов'Ñзано із проходами малюваннÑ." @@ -9641,26 +9715,6 @@ msgstr "" "Щоб уÑе працювало Ñк Ñлід, влаÑтивіÑть шлÑху (path) має вказувати на " "коректний вузол Spatial." -#: scene/3d/scenario_fx.cpp -msgid "WorldEnvironment needs an Environment resource." -msgstr "WorldEnvironment потребує реÑурÑу Environment." - -#: scene/3d/scenario_fx.cpp -msgid "" -"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." -msgstr "" -"У Ñцені (або наборі екземплÑрів Ñцен) може бути лише один елемент " -"WorldEnvironment." - -#: scene/3d/scenario_fx.cpp -msgid "" -"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " -"this environment's Background Mode to Canvas (for 2D scenes)." -msgstr "" -"Цей Ð·Ð°Ð¿Ð¸Ñ WorldEnvironment проігноровано. Ðбо додайте Ð·Ð°Ð¿Ð¸Ñ Camera (Ð´Ð»Ñ " -"проÑторових Ñцен) або вÑтановіть Ð´Ð»Ñ Background Mode цього Ñередовища " -"Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Canvas (Ð´Ð»Ñ Ð´Ð²Ð¾Ð²Ð¸Ð¼Ñ–Ñ€Ð½Ð¸Ñ… Ñцен)." - #: scene/3d/soft_body.cpp msgid "This body will be ignored until you set a mesh" msgstr "Це тіло буде проігноровано, аж доки ви не вÑтановите Ñітку" @@ -9690,6 +9744,26 @@ msgstr "" "VehicleWheel Ñлугує Ð´Ð»Ñ Ð·Ð°Ð±ÐµÐ·Ð¿ÐµÑ‡ÐµÐ½Ð½Ñ Ñ€Ð¾Ð±Ð¾Ñ‚Ð¸ ÑиÑтеми ÐºÐ¾Ð»Ñ–Ñ Ñƒ VehicleBody. " "Будь лаÑка, викориÑтовуйте цей елемент Ñк дочірній елемент вузла VehicleBody." +#: scene/3d/world_environment.cpp +msgid "WorldEnvironment needs an Environment resource." +msgstr "WorldEnvironment потребує реÑурÑу Environment." + +#: scene/3d/world_environment.cpp +msgid "" +"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." +msgstr "" +"У Ñцені (або наборі екземплÑрів Ñцен) може бути лише один елемент " +"WorldEnvironment." + +#: scene/3d/world_environment.cpp +msgid "" +"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " +"this environment's Background Mode to Canvas (for 2D scenes)." +msgstr "" +"Цей Ð·Ð°Ð¿Ð¸Ñ WorldEnvironment проігноровано. Ðбо додайте Ð·Ð°Ð¿Ð¸Ñ Camera (Ð´Ð»Ñ " +"проÑторових Ñцен) або вÑтановіть Ð´Ð»Ñ Background Mode цього Ñередовища " +"Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Canvas (Ð´Ð»Ñ Ð´Ð²Ð¾Ð²Ð¸Ð¼Ñ–Ñ€Ð½Ð¸Ñ… Ñцен)." + #: scene/animation/animation_blend_tree.cpp msgid "On BlendTree node '%s', animation not found: '%s'" msgstr "У вузлі BlendTree «%s» не знайдено анімації: «%s»" @@ -9733,11 +9807,20 @@ msgstr "" "Цей вузол вважаєтьÑÑ Ð·Ð°Ñтарілим. СкориÑтайтеÑÑ Ð·Ð°Ð¼Ñ–Ñть нього AnimationTree." #: scene/gui/color_picker.cpp +msgid "Pick a color from the screen." +msgstr "Вибрати колір з екрана." + +#: scene/gui/color_picker.cpp msgid "Raw Mode" msgstr "Raw (Ñирий) режим" #: scene/gui/color_picker.cpp -msgid "Add current color as a preset" +msgid "Switch between hexadecimal and code values." +msgstr "ÐŸÐµÑ€ÐµÐ¼Ð¸ÐºÐ°Ð½Ð½Ñ Ð¼Ñ–Ð¶ шіÑтнадцÑтковими значеннÑми Ñ– кодами." + +#: scene/gui/color_picker.cpp +#, fuzzy +msgid "Add current color as a preset." msgstr "Додати поточний колір в ÑкоÑті преÑету" #: scene/gui/dialogs.cpp @@ -9833,6 +9916,18 @@ msgstr "ÐŸÑ€Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð¾Ð´Ð½Ð¾Ñ€Ñ–Ð´Ð½Ð¾Ð³Ð¾." msgid "Varyings can only be assigned in vertex function." msgstr "Змінні величини можна пов'Ñзувати лише із функцією вузлів." +#~ msgid "Warnings:" +#~ msgstr "ПопередженнÑ:" + +#~ msgid "Font Size:" +#~ msgstr "Розмір шрифту:" + +#~ msgid "Line:" +#~ msgstr "Ð Ñдок:" + +#~ msgid "Col:" +#~ msgstr "Колонка:" + #~ msgid "OrientedPathFollow only works when set as a child of a Path node." #~ msgstr "OrientedPathFollow працюватиме лише Ñк дочірній елемент вузла Path." diff --git a/editor/translations/ur_PK.po b/editor/translations/ur_PK.po index e0d4e7628b..d77307b020 100644 --- a/editor/translations/ur_PK.po +++ b/editor/translations/ur_PK.po @@ -540,20 +540,12 @@ msgstr "" msgid "Reset Zoom" msgstr "" -#: editor/code_editor.cpp -msgid "Warnings:" -msgstr "" - -#: editor/code_editor.cpp -msgid "Font Size:" -msgstr "" - -#: editor/code_editor.cpp -msgid "Line:" +#: editor/code_editor.cpp modules/mono/editor/mono_bottom_panel.cpp +msgid "Warnings" msgstr "" #: editor/code_editor.cpp -msgid "Col:" +msgid "Line and column numbers." msgstr "" #: editor/connections_dialog.cpp @@ -849,8 +841,8 @@ msgstr "" #: editor/dependency_editor.cpp editor/editor_audio_buses.cpp #: editor/editor_file_dialog.cpp editor/editor_node.cpp #: editor/filesystem_dock.cpp editor/plugins/item_list_editor_plugin.cpp -#: editor/project_export.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_dock.cpp +#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp +#: editor/project_settings_editor.cpp editor/scene_tree_dock.cpp msgid "Delete" msgstr "" @@ -1105,7 +1097,7 @@ msgid "Add Bus" msgstr "" #: editor/editor_audio_buses.cpp -msgid "Create a new Bus Layout." +msgid "Add a new Audio Bus to this layout." msgstr "" #: editor/editor_audio_buses.cpp editor/editor_properties.cpp @@ -1135,6 +1127,10 @@ msgstr "" msgid "Load the default Bus Layout." msgstr "" +#: editor/editor_audio_buses.cpp +msgid "Create a new Bus Layout." +msgstr "" + #: editor/editor_autoload_settings.cpp msgid "Invalid name." msgstr "" @@ -2319,7 +2315,7 @@ msgid "Save & Restart" msgstr "" #: editor/editor_node.cpp -msgid "Spins when the editor window repaints!" +msgid "Spins when the editor window redraws." msgstr "" #: editor/editor_node.cpp @@ -3367,24 +3363,6 @@ msgid "Create Polygon" msgstr "سب سکریپشن بنائیں" #: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Edit Polygon" -msgstr "سب سکریپشن بنائیں" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Insert Point" -msgstr "" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Edit Polygon (Remove Point)" -msgstr "" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Remove Polygon And Point" -msgstr ".تمام کا انتخاب" - -#: editor/plugins/abstract_polygon_2d_editor.cpp #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #, fuzzy @@ -3404,6 +3382,24 @@ msgstr "" msgid "Erase points." msgstr ".تمام کا انتخاب" +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Edit Polygon" +msgstr "سب سکریپشن بنائیں" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Insert Point" +msgstr "" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Edit Polygon (Remove Point)" +msgstr "" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Remove Polygon And Point" +msgstr ".تمام کا انتخاب" + #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #: editor/plugins/animation_player_editor_plugin.cpp @@ -4194,6 +4190,16 @@ msgid "Move CanvasItem" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp +msgid "Presets for the anchors and margins values of a Control node." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp +msgid "" +"Children of containers have their anchors and margins values overridden by " +"their parent." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp msgid "Anchors only" msgstr "" @@ -5101,6 +5107,12 @@ msgid "Create UV Map" msgstr "" #: editor/plugins/polygon_2d_editor_plugin.cpp +msgid "" +"Polygon 2D has internal vertices, so it can no longer be edited in the " +"viewport." +msgstr "" + +#: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Create Polygon & UV" msgstr "" @@ -6198,7 +6210,7 @@ msgid "Post" msgstr "" #: editor/plugins/spatial_editor_plugin.cpp -msgid "Name-less gizmo" +msgid "Nameless gizmo" msgstr "" #: editor/plugins/sprite_editor_plugin.cpp @@ -6275,7 +6287,11 @@ msgid "(empty)" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animations" +msgid "Animations:" +msgstr "" + +#: editor/plugins/sprite_frames_editor_plugin.cpp +msgid "New Animation" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp @@ -6287,7 +6303,7 @@ msgid "Loop" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animation Frames" +msgid "Animation Frames:" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp @@ -7091,6 +7107,19 @@ msgstr "" #: editor/project_manager.cpp msgid "" +"The following project settings file does not specify the version of Godot " +"through which it was created.\n" +"\n" +"%s\n" +"\n" +"If you proceed with opening it, it will be converted to Godot's current " +"configuration file format.\n" +"Warning: You will not be able to open the project with previous versions of " +"the engine anymore." +msgstr "" + +#: editor/project_manager.cpp +msgid "" "The following project settings file was generated by an older engine " "version, and needs to be converted for this version:\n" "\n" @@ -8590,10 +8619,6 @@ msgid "Build Project" msgstr "" #: modules/mono/editor/mono_bottom_panel.cpp -msgid "Warnings" -msgstr "" - -#: modules/mono/editor/mono_bottom_panel.cpp msgid "View log" msgstr "" @@ -9225,6 +9250,13 @@ msgid "" "ParallaxLayer node only works when set as child of a ParallaxBackground node." msgstr "" +#: scene/2d/particles_2d.cpp +msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles2D node instead. You can use the \"Convert to " +"CPUParticles\" option for this purpose." +msgstr "" + #: scene/2d/particles_2d.cpp scene/3d/particles.cpp msgid "" "A material to process the particles is not assigned, so no behavior is " @@ -9380,6 +9412,13 @@ msgstr "" #: scene/3d/particles.cpp msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles node instead. You can use the \"Convert to CPUParticles" +"\" option for this purpose." +msgstr "" + +#: scene/3d/particles.cpp +msgid "" "Nothing is visible because meshes have not been assigned to draw passes." msgstr "" @@ -9410,21 +9449,6 @@ msgstr "" msgid "Path property must point to a valid Spatial node to work." msgstr "" -#: scene/3d/scenario_fx.cpp -msgid "WorldEnvironment needs an Environment resource." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " -"this environment's Background Mode to Canvas (for 2D scenes)." -msgstr "" - #: scene/3d/soft_body.cpp msgid "This body will be ignored until you set a mesh" msgstr "" @@ -9448,6 +9472,21 @@ msgid "" "it as a child of a VehicleBody." msgstr "" +#: scene/3d/world_environment.cpp +msgid "WorldEnvironment needs an Environment resource." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " +"this environment's Background Mode to Canvas (for 2D scenes)." +msgstr "" + #: scene/animation/animation_blend_tree.cpp msgid "On BlendTree node '%s', animation not found: '%s'" msgstr "" @@ -9489,11 +9528,19 @@ msgid "This node has been deprecated. Use AnimationTree instead." msgstr "" #: scene/gui/color_picker.cpp +msgid "Pick a color from the screen." +msgstr "" + +#: scene/gui/color_picker.cpp msgid "Raw Mode" msgstr "" #: scene/gui/color_picker.cpp -msgid "Add current color as a preset" +msgid "Switch between hexadecimal and code values." +msgstr "" + +#: scene/gui/color_picker.cpp +msgid "Add current color as a preset." msgstr "" #: scene/gui/dialogs.cpp diff --git a/editor/translations/vi.po b/editor/translations/vi.po index ad0feaa6a1..e7ae7be36f 100644 --- a/editor/translations/vi.po +++ b/editor/translations/vi.po @@ -557,23 +557,14 @@ msgstr "Thu nhá»" msgid "Reset Zoom" msgstr "Äặt lại phóng" -#: editor/code_editor.cpp -msgid "Warnings:" +#: editor/code_editor.cpp modules/mono/editor/mono_bottom_panel.cpp +msgid "Warnings" msgstr "" #: editor/code_editor.cpp -msgid "Font Size:" +msgid "Line and column numbers." msgstr "" -#: editor/code_editor.cpp -msgid "Line:" -msgstr "Dòng:" - -#: editor/code_editor.cpp -#, fuzzy -msgid "Col:" -msgstr "Col:" - #: editor/connections_dialog.cpp msgid "Method in target Node must be specified!" msgstr "Cách thức trong Node được chá»n phải được ghi rõ!" @@ -876,8 +867,8 @@ msgstr "" #: editor/dependency_editor.cpp editor/editor_audio_buses.cpp #: editor/editor_file_dialog.cpp editor/editor_node.cpp #: editor/filesystem_dock.cpp editor/plugins/item_list_editor_plugin.cpp -#: editor/project_export.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_dock.cpp +#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp +#: editor/project_settings_editor.cpp editor/scene_tree_dock.cpp msgid "Delete" msgstr "Xóa" @@ -1129,7 +1120,7 @@ msgid "Add Bus" msgstr "" #: editor/editor_audio_buses.cpp -msgid "Create a new Bus Layout." +msgid "Add a new Audio Bus to this layout." msgstr "" #: editor/editor_audio_buses.cpp editor/editor_properties.cpp @@ -1158,6 +1149,10 @@ msgstr "" msgid "Load the default Bus Layout." msgstr "" +#: editor/editor_audio_buses.cpp +msgid "Create a new Bus Layout." +msgstr "" + #: editor/editor_autoload_settings.cpp msgid "Invalid name." msgstr "" @@ -2360,7 +2355,7 @@ msgid "Save & Restart" msgstr "" #: editor/editor_node.cpp -msgid "Spins when the editor window repaints!" +msgid "Spins when the editor window redraws." msgstr "" #: editor/editor_node.cpp @@ -3428,23 +3423,6 @@ msgid "Create Polygon" msgstr "Tạo" #: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Edit Polygon" -msgstr "Tạo" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Insert Point" -msgstr "" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Edit Polygon (Remove Point)" -msgstr "" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Remove Polygon And Point" -msgstr "" - -#: editor/plugins/abstract_polygon_2d_editor.cpp #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #, fuzzy @@ -3463,6 +3441,23 @@ msgstr "" msgid "Erase points." msgstr "" +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Edit Polygon" +msgstr "Tạo" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Insert Point" +msgstr "" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Edit Polygon (Remove Point)" +msgstr "" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Remove Polygon And Point" +msgstr "" + #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #: editor/plugins/animation_player_editor_plugin.cpp @@ -4263,6 +4258,16 @@ msgid "Move CanvasItem" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp +msgid "Presets for the anchors and margins values of a Control node." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp +msgid "" +"Children of containers have their anchors and margins values overridden by " +"their parent." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp msgid "Anchors only" msgstr "" @@ -5165,6 +5170,12 @@ msgid "Create UV Map" msgstr "" #: editor/plugins/polygon_2d_editor_plugin.cpp +msgid "" +"Polygon 2D has internal vertices, so it can no longer be edited in the " +"viewport." +msgstr "" + +#: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Create Polygon & UV" msgstr "" @@ -6270,7 +6281,7 @@ msgid "Post" msgstr "" #: editor/plugins/spatial_editor_plugin.cpp -msgid "Name-less gizmo" +msgid "Nameless gizmo" msgstr "" #: editor/plugins/sprite_editor_plugin.cpp @@ -6347,8 +6358,14 @@ msgid "(empty)" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animations" -msgstr "" +#, fuzzy +msgid "Animations:" +msgstr "Các Công cụ Animation" + +#: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "New Animation" +msgstr "Tạo Animation má»›i" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed (FPS):" @@ -6359,8 +6376,9 @@ msgid "Loop" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animation Frames" -msgstr "" +#, fuzzy +msgid "Animation Frames:" +msgstr "Tên Animation:" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Insert Empty (Before)" @@ -7165,6 +7183,19 @@ msgstr "" #: editor/project_manager.cpp msgid "" +"The following project settings file does not specify the version of Godot " +"through which it was created.\n" +"\n" +"%s\n" +"\n" +"If you proceed with opening it, it will be converted to Godot's current " +"configuration file format.\n" +"Warning: You will not be able to open the project with previous versions of " +"the engine anymore." +msgstr "" + +#: editor/project_manager.cpp +msgid "" "The following project settings file was generated by an older engine " "version, and needs to be converted for this version:\n" "\n" @@ -8658,10 +8689,6 @@ msgid "Build Project" msgstr "" #: modules/mono/editor/mono_bottom_panel.cpp -msgid "Warnings" -msgstr "" - -#: modules/mono/editor/mono_bottom_panel.cpp msgid "View log" msgstr "" @@ -9295,6 +9322,13 @@ msgid "" "ParallaxLayer node only works when set as child of a ParallaxBackground node." msgstr "" +#: scene/2d/particles_2d.cpp +msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles2D node instead. You can use the \"Convert to " +"CPUParticles\" option for this purpose." +msgstr "" + #: scene/2d/particles_2d.cpp scene/3d/particles.cpp msgid "" "A material to process the particles is not assigned, so no behavior is " @@ -9450,6 +9484,13 @@ msgstr "" #: scene/3d/particles.cpp msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles node instead. You can use the \"Convert to CPUParticles" +"\" option for this purpose." +msgstr "" + +#: scene/3d/particles.cpp +msgid "" "Nothing is visible because meshes have not been assigned to draw passes." msgstr "" @@ -9480,21 +9521,6 @@ msgstr "" msgid "Path property must point to a valid Spatial node to work." msgstr "" -#: scene/3d/scenario_fx.cpp -msgid "WorldEnvironment needs an Environment resource." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " -"this environment's Background Mode to Canvas (for 2D scenes)." -msgstr "" - #: scene/3d/soft_body.cpp msgid "This body will be ignored until you set a mesh" msgstr "" @@ -9518,6 +9544,21 @@ msgid "" "it as a child of a VehicleBody." msgstr "" +#: scene/3d/world_environment.cpp +msgid "WorldEnvironment needs an Environment resource." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " +"this environment's Background Mode to Canvas (for 2D scenes)." +msgstr "" + #: scene/animation/animation_blend_tree.cpp msgid "On BlendTree node '%s', animation not found: '%s'" msgstr "" @@ -9560,11 +9601,19 @@ msgid "This node has been deprecated. Use AnimationTree instead." msgstr "" #: scene/gui/color_picker.cpp +msgid "Pick a color from the screen." +msgstr "" + +#: scene/gui/color_picker.cpp msgid "Raw Mode" msgstr "" #: scene/gui/color_picker.cpp -msgid "Add current color as a preset" +msgid "Switch between hexadecimal and code values." +msgstr "" + +#: scene/gui/color_picker.cpp +msgid "Add current color as a preset." msgstr "" #: scene/gui/dialogs.cpp @@ -9650,6 +9699,13 @@ msgstr "" msgid "Varyings can only be assigned in vertex function." msgstr "" +#~ msgid "Line:" +#~ msgstr "Dòng:" + +#, fuzzy +#~ msgid "Col:" +#~ msgstr "Col:" + #, fuzzy #~ msgid "Remove Split" #~ msgstr "Bá» lá»±a chá»n" diff --git a/editor/translations/zh_CN.po b/editor/translations/zh_CN.po index 6071ac66c8..770b249d11 100644 --- a/editor/translations/zh_CN.po +++ b/editor/translations/zh_CN.po @@ -34,18 +34,19 @@ # 刘庆文 <liuqingwen@163.com>, 2018. # Haowen Liu <liu.haowen.andy@gmail.com>, 2018. # tangdou1 <1093505442@qq.com>, 2018. -# yzt <834950797@qq.com>, 2018. +# yzt <834950797@qq.com>, 2018, 2019. # DKLost <514dklost@gmail.com>, 2018. # thanksshu <hezihanshangyuan@gmail.com>, 2018. # Jsheng <yangea@outlook.com>, 2019. # Zhang Zhibo <zzhibo98@gmail.com>, 2019. # ws00010203 <ws00010203@hotmail.com>, 2019. +# Song DongHui <14729626293@163.com>, 2019. msgid "" msgstr "" "Project-Id-Version: Chinese (Simplified) (Godot Engine)\n" "POT-Creation-Date: 2018-01-20 12:15+0200\n" -"PO-Revision-Date: 2019-01-26 21:22+0000\n" -"Last-Translator: ws00010203 <ws00010203@hotmail.com>\n" +"PO-Revision-Date: 2019-02-18 08:54+0000\n" +"Last-Translator: yzt <834950797@qq.com>\n" "Language-Team: Chinese (Simplified) <https://hosted.weblate.org/projects/" "godot-engine/godot/zh_Hans/>\n" "Language: zh_CN\n" @@ -573,21 +574,14 @@ msgstr "缩å°" msgid "Reset Zoom" msgstr "é‡ç½®ç¼©æ”¾" -#: editor/code_editor.cpp -msgid "Warnings:" -msgstr "è¦å‘Šï¼š" - -#: editor/code_editor.cpp -msgid "Font Size:" -msgstr "å—体大å°:" - -#: editor/code_editor.cpp -msgid "Line:" -msgstr "行:" +#: editor/code_editor.cpp modules/mono/editor/mono_bottom_panel.cpp +msgid "Warnings" +msgstr "è¦å‘Š" #: editor/code_editor.cpp -msgid "Col:" -msgstr "列:" +#, fuzzy +msgid "Line and column numbers." +msgstr "行å·å’Œåˆ—å·" #: editor/connections_dialog.cpp msgid "Method in target Node must be specified!" @@ -880,8 +874,8 @@ msgstr "åˆ é™¤é€‰ä¸çš„æ–‡ä»¶ï¼Ÿ" #: editor/dependency_editor.cpp editor/editor_audio_buses.cpp #: editor/editor_file_dialog.cpp editor/editor_node.cpp #: editor/filesystem_dock.cpp editor/plugins/item_list_editor_plugin.cpp -#: editor/project_export.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_dock.cpp +#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp +#: editor/project_settings_editor.cpp editor/scene_tree_dock.cpp msgid "Delete" msgstr "åˆ é™¤" @@ -1135,8 +1129,9 @@ msgid "Add Bus" msgstr "æ·»åŠ Bus" #: editor/editor_audio_buses.cpp -msgid "Create a new Bus Layout." -msgstr "创建一个新的总线布局。" +#, fuzzy +msgid "Add a new Audio Bus to this layout." +msgstr "将音频Bus布局ä¿å˜ä¸º..." #: editor/editor_audio_buses.cpp editor/editor_properties.cpp #: editor/plugins/animation_player_editor_plugin.cpp editor/property_editor.cpp @@ -1164,6 +1159,10 @@ msgstr "åŠ è½½é»˜è®¤" msgid "Load the default Bus Layout." msgstr "åŠ è½½é»˜è®¤æ€»çº¿å¸ƒå±€ã€‚" +#: editor/editor_audio_buses.cpp +msgid "Create a new Bus Layout." +msgstr "创建一个新的总线布局。" + #: editor/editor_autoload_settings.cpp msgid "Invalid name." msgstr "åç§°éžæ³•:。" @@ -2370,7 +2369,8 @@ msgid "Save & Restart" msgstr "ä¿å˜å¹¶é‡å¯" #: editor/editor_node.cpp -msgid "Spins when the editor window repaints!" +#, fuzzy +msgid "Spins when the editor window redraws." msgstr "æ—‹è½¬æ—¶ï¼Œé‡æ–°ç»˜åˆ¶ç¼–辑器窗å£ï¼" #: editor/editor_node.cpp @@ -3282,17 +3282,16 @@ msgstr "釿–°å¯¼å…¥" #: editor/import_dock.cpp msgid "Save scenes, re-import and restart" -msgstr "" +msgstr "ä¿å˜åœºæ™¯ï¼Œé‡æ–°å¯¼å…¥ï¼Œä»Žå¤´å¼€å§‹" #: editor/import_dock.cpp -#, fuzzy msgid "Changing the type of an imported file requires editor restart." -msgstr "改å˜è§†é¢‘驱动需è¦é‡å¯ç¼–辑器。" +msgstr "改å˜è¿™ä¸ªå¯¼å…¥çš„æ–‡ä»¶ç±»åž‹åŽéœ€è¦é‡å¯ç¼–辑器。" #: editor/import_dock.cpp msgid "" "WARNING: Assets exist that use this resource, they may stop loading properly." -msgstr "" +msgstr "è¦å‘Šï¼šèµ„æºä½¿ç”¨å†²çªï¼Œå°†ä¼šåœæ¢åŠ è½½ã€‚" #: editor/inspector_dock.cpp msgid "Failed to load resource." @@ -3417,22 +3416,6 @@ msgid "Create Polygon" msgstr "创建多边形" #: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Edit Polygon" -msgstr "编辑多边形" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Insert Point" -msgstr "æ’入点" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Edit Polygon (Remove Point)" -msgstr "编辑多边形(移除顶点)" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Remove Polygon And Point" -msgstr "移除多边形åŠé¡¶ç‚¹" - -#: editor/plugins/abstract_polygon_2d_editor.cpp #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp msgid "Create points." @@ -3453,6 +3436,22 @@ msgstr "" msgid "Erase points." msgstr "擦除点。" +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Edit Polygon" +msgstr "编辑多边形" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Insert Point" +msgstr "æ’入点" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Edit Polygon (Remove Point)" +msgstr "编辑多边形(移除顶点)" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Remove Polygon And Point" +msgstr "移除多边形åŠé¡¶ç‚¹" + #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #: editor/plugins/animation_player_editor_plugin.cpp @@ -4241,6 +4240,16 @@ msgid "Move CanvasItem" msgstr "移动 CanvasItem" #: editor/plugins/canvas_item_editor_plugin.cpp +msgid "Presets for the anchors and margins values of a Control node." +msgstr "控件节点的定ä½ç‚¹å’Œè¾¹è·å€¼çš„预设。" + +#: editor/plugins/canvas_item_editor_plugin.cpp +msgid "" +"Children of containers have their anchors and margins values overridden by " +"their parent." +msgstr "容器的å级的锚点和边è·å€¼è¢«å…¶çˆ¶å®¹å™¨é‡å†™ã€‚" + +#: editor/plugins/canvas_item_editor_plugin.cpp msgid "Anchors only" msgstr "仅锚点" @@ -4902,7 +4911,7 @@ msgstr "清除Emission Mask(å‘å°„å±è”½ï¼‰" #: editor/plugins/particles_2d_editor_plugin.cpp #: editor/plugins/particles_editor_plugin.cpp msgid "Convert to CPUParticles" -msgstr "转æ¢ä¸º CPU ç²’å" +msgstr "转æ¢ä¸º CPUç²’å" #: editor/plugins/particles_2d_editor_plugin.cpp #: editor/plugins/particles_editor_plugin.cpp @@ -5138,6 +5147,12 @@ msgid "Create UV Map" msgstr "创建UV贴图" #: editor/plugins/polygon_2d_editor_plugin.cpp +msgid "" +"Polygon 2D has internal vertices, so it can no longer be edited in the " +"viewport." +msgstr "" + +#: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Create Polygon & UV" msgstr "创建多边形和 UV" @@ -5146,12 +5161,10 @@ msgid "Create Internal Vertex" msgstr "创建内部顶点" #: editor/plugins/polygon_2d_editor_plugin.cpp -#, fuzzy msgid "Remove Internal Vertex" msgstr "移除曲线内控制点" #: editor/plugins/polygon_2d_editor_plugin.cpp -#, fuzzy msgid "Invalid Polygon (need 3 different vertices)" msgstr "æ— æ•ˆçš„å¤šè¾¹å½¢ï¼ˆéœ€è¦ä¸‰ä¸ªæŽ§åˆ¶ç‚¹ï¼‰" @@ -5160,9 +5173,8 @@ msgid "Add Custom Polygon" msgstr "æ·»åŠ è‡ªå®šä¹‰å¤šè¾¹å½¢" #: editor/plugins/polygon_2d_editor_plugin.cpp -#, fuzzy msgid "Remove Custom Polygon" -msgstr "移除多边形åŠé¡¶ç‚¹" +msgstr "åˆ é™¤è‡ªå®šä¹‰å¤šè¾¹å½¢" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Transform UV Map" @@ -5189,14 +5201,12 @@ msgid "UV" msgstr "UV" #: editor/plugins/polygon_2d_editor_plugin.cpp -#, fuzzy msgid "Points" msgstr "点" #: editor/plugins/polygon_2d_editor_plugin.cpp -#, fuzzy msgid "Polygons" -msgstr "多边形->UV" +msgstr "多边形-" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Bones" @@ -5245,7 +5255,6 @@ msgid "Paint weights with specified intensity." msgstr "使用指定的强度进行æƒé‡ç»˜åˆ¶ã€‚" #: editor/plugins/polygon_2d_editor_plugin.cpp -#, fuzzy msgid "Unpaint weights with specified intensity." msgstr "使用指定强度清除æƒé‡ç»˜åˆ¶ã€‚" @@ -6230,8 +6239,8 @@ msgid "Post" msgstr "å‘布(Post)" #: editor/plugins/spatial_editor_plugin.cpp -msgid "Name-less gizmo" -msgstr "" +msgid "Nameless gizmo" +msgstr "未命åçš„Gizmo" #: editor/plugins/sprite_editor_plugin.cpp msgid "Sprite is empty!" @@ -6306,8 +6315,12 @@ msgid "(empty)" msgstr "(空)" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animations" -msgstr "动画" +msgid "Animations:" +msgstr "动画:" + +#: editor/plugins/sprite_frames_editor_plugin.cpp +msgid "New Animation" +msgstr "新建动画" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed (FPS):" @@ -6318,8 +6331,8 @@ msgid "Loop" msgstr "循环" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animation Frames" -msgstr "动画帧" +msgid "Animation Frames:" +msgstr "动画帧:" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Insert Empty (Before)" @@ -6346,9 +6359,8 @@ msgid "Set Region Rect" msgstr "设置纹ç†åŒºåŸŸ" #: editor/plugins/texture_region_editor_plugin.cpp -#, fuzzy msgid "Set Margin" -msgstr "设置处ç†ç¨‹åº" +msgstr "设置边è·" #: editor/plugins/texture_region_editor_plugin.cpp msgid "Snap Mode:" @@ -6592,14 +6604,12 @@ msgid "Clear transform" msgstr "æ¸…é™¤å˜æ¢" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Add Texture(s) to TileSet." -msgstr "æ·»åŠ çº¹ç†åˆ°ç£è´´é›†" +msgstr "æ·»åŠ çº¹ç†åˆ°ç£è´´é›†ã€‚" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Remove selected Texture from TileSet." -msgstr "从ç£è´´é›†ä¸åˆ 除当å‰çº¹ç†" +msgstr "从ç£è´´é›†ä¸åˆ 除当å‰çº¹ç†ã€‚" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Create from Scene" @@ -6640,27 +6650,24 @@ msgid "Display Tile Names (Hold Alt Key)" msgstr "显示ç£è´´çš„åå—ï¼ˆæŒ‰ä½ Alt 键)" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Remove selected texture? This will remove all tiles which use it." -msgstr "确定移除选ä¸çš„纹ç†ä»¥åŠã€æ‰€æœ‰ã€‘使用它的ã€ç£è´´é›†ã€‘å—?" +msgstr "åˆ é™¤é€‰å®šçš„çº¹ç†ï¼Ÿè¿™å°†åˆ 除使用它的所有ç£è´´ã€‚" #: editor/plugins/tile_set_editor_plugin.cpp msgid "You haven't selected a texture to remove." msgstr "请先选择è¦ç§»é™¤çš„纹ç†ã€‚" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Create from scene? This will overwrite all current tiles." -msgstr "ä»Žåœºæ™¯åˆ›å»ºï¼Ÿè¿™å°†è¦†ç›–æ‰€æœ‰å½“å‰æ ‡é¢˜ã€‚" +msgstr "从场景创建?这将覆盖所有当å‰ç£è´´ã€‚" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Merge from scene?" msgstr "确定è¦åˆå¹¶åœºæ™¯ï¼Ÿ" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Remove Texture" -msgstr "移除模æ¿" +msgstr "åˆ é™¤çº¹ç†" #: editor/plugins/tile_set_editor_plugin.cpp msgid "%s file(s) were not added because was already on the list." @@ -6726,95 +6733,80 @@ msgstr "" "点击选择å¦ä¸€ä¸ªç£è´´è¿›è¡Œç¼–辑。" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Set Tile Region" -msgstr "设置纹ç†åŒºåŸŸ" +msgstr "设置ç£è´´åŒºåŸŸ" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Create Tile" -msgstr "新建目录" +msgstr "创建ç£è´´" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Set Tile Icon" -msgstr "" +msgstr "设置纹ç†å›¾æ ‡" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Edit Tile Bitmask" -msgstr "编辑ç›é€‰å™¨" +msgstr "编辑ç£è´´ä½æŽ©ç " #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Edit Collision Polygon" -msgstr "编辑已å˜åœ¨çš„多边形:" +msgstr "编辑碰撞多边形" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Edit Occlusion Polygon" -msgstr "编辑多边形" +msgstr "ç¼–è¾‘é®æŒ¡å¤šè¾¹å½¢" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Edit Navigation Polygon" -msgstr "创建导航多边形" +msgstr "编辑导航多边形" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Paste Tile Bitmask" -msgstr "ç²˜è´´ä½æŽ©ç 。" +msgstr "粘贴ç£è´´ä½æŽ©ç " #: editor/plugins/tile_set_editor_plugin.cpp msgid "Clear Tile Bitmask" -msgstr "" +msgstr "æ¸…é™¤ä½æŽ©ç " #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Remove Tile" -msgstr "移除模æ¿" +msgstr "移除ç£è´´" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Remove Collision Polygon" -msgstr "移除多边形åŠé¡¶ç‚¹" +msgstr "åˆ é™¤ç¢°æ’žå¤šè¾¹å½¢" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Remove Occlusion Polygon" -msgstr "æ·»åŠ é®å…‰å¤šè¾¹å½¢" +msgstr "åˆ é™¤é®æŒ¡å¤šè¾¹å½¢" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Remove Navigation Polygon" -msgstr "创建导航多边形" +msgstr "åˆ é™¤å¯¼èˆªå¤šè¾¹å½¢" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Edit Tile Priority" -msgstr "编辑ç›é€‰å™¨" +msgstr "编辑ç£è´´ä¼˜å…ˆçº§" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Edit Tile Z Index" -msgstr "" +msgstr "编辑纹ç†çš„Zåæ ‡" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Create Collision Polygon" -msgstr "创建导航多边形" +msgstr "创建碰撞多边形" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Create Occlusion Polygon" -msgstr "æ·»åŠ é®å…‰å¤šè¾¹å½¢" +msgstr "åˆ›å»ºé®æŒ¡å¤šè¾¹å½¢" #: editor/plugins/tile_set_editor_plugin.cpp msgid "This property can't be changed." msgstr "ä¸èƒ½ä¿®æ”¹è¯¥å±žæ€§ã€‚" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "TileSet" -msgstr "ç –å—集" +msgstr "瓦片集" #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Vertex" @@ -6923,9 +6915,8 @@ msgid "Feature List:" msgstr "功能列表:" #: editor/project_export.cpp -#, fuzzy msgid "Script" -msgstr "新建脚本" +msgstr "脚本" #: editor/project_export.cpp msgid "Script Export Mode:" @@ -6945,7 +6936,7 @@ msgstr "使用下列密ç åŠ å¯†" #: editor/project_export.cpp msgid "Invalid Encryption Key (must be 64 characters long)" -msgstr "" +msgstr "æ— æ•ˆçš„åŠ å¯†å¯†é’¥ï¼ˆé•¿åº¦å¿…é¡»ä¸º64个å—符)" #: editor/project_export.cpp msgid "Script Encryption Key (256-bits as hex):" @@ -7088,11 +7079,11 @@ msgstr "æµè§ˆ" #: editor/project_manager.cpp msgid "Renderer:" -msgstr "" +msgstr "渲染器:" #: editor/project_manager.cpp msgid "OpenGL ES 3.0" -msgstr "" +msgstr "OpenGL ES 3.0" #: editor/project_manager.cpp msgid "" @@ -7101,10 +7092,14 @@ msgid "" "Incompatible with older hardware\n" "Not recommended for web games" msgstr "" +"更高的视觉质é‡\n" +"所有å¯ç”¨åŠŸèƒ½\n" +"与旧硬件ä¸å…¼å®¹\n" +"䏿ލè用于网络游æˆ" #: editor/project_manager.cpp msgid "OpenGL ES 2.0" -msgstr "" +msgstr "OpenGL ES 2.0" #: editor/project_manager.cpp msgid "" @@ -7113,19 +7108,22 @@ msgid "" "Works on most hardware\n" "Recommended for web games" msgstr "" +"较低的视觉质é‡\n" +"æŸäº›åŠŸèƒ½ä¸å¯ç”¨\n" +"适用于大多数硬件\n" +"推è用于网络游æˆ" #: editor/project_manager.cpp msgid "Renderer can be changed later, but scenes may need to be adjusted." -msgstr "" +msgstr "渲染器å¯ä»¥ç¨åŽæ›´æ”¹ï¼Œä½†å¯èƒ½éœ€è¦è°ƒæ•´åœºæ™¯ã€‚" #: editor/project_manager.cpp msgid "Unnamed Project" msgstr "未命å项目" #: editor/project_manager.cpp -#, fuzzy msgid "Can't open project at '%s'." -msgstr "æ— æ³•æ‰“å¼€é¡¹ç›®" +msgstr "æ— æ³•æ‰“å¼€ä½äºŽâ€œ%sâ€çš„相应项目." #: editor/project_manager.cpp msgid "Are you sure to open more than one project?" @@ -7133,6 +7131,25 @@ msgstr "æ‚¨ç¡®å®šè¦æ‰“开多个项目å—?" #: editor/project_manager.cpp msgid "" +"The following project settings file does not specify the version of Godot " +"through which it was created.\n" +"\n" +"%s\n" +"\n" +"If you proceed with opening it, it will be converted to Godot's current " +"configuration file format.\n" +"Warning: You will not be able to open the project with previous versions of " +"the engine anymore." +msgstr "" +"以下项目设置文件没有指定创建它的Godot版本:\n" +"\n" +"%s\n" +"\n" +"å¦‚æžœä½ ç»§ç»æ‰“开它,它将被转æ¢ä¸ºGodot的当å‰é…ç½®æ–‡ä»¶æ ¼å¼ã€‚\n" +"è¦å‘Šï¼šæ‚¨å°†æ— 法å†ä½¿ç”¨ä»¥å‰ç‰ˆæœ¬çš„引擎打开项目。" + +#: editor/project_manager.cpp +msgid "" "The following project settings file was generated by an older engine " "version, and needs to be converted for this version:\n" "\n" @@ -7142,12 +7159,16 @@ msgid "" "Warning: You will not be able to open the project with previous versions of " "the engine anymore." msgstr "" +"以下项目设置文件是由旧的引擎版本生æˆçš„,需è¦ä¸ºæ¤ç‰ˆæœ¬è½¬æ¢ï¼š\n" +"%s\n" +"是å¦è¦è½¬æ¢å®ƒï¼Ÿ\n" +"è¦å‘Šï¼šæ‚¨å°†æ— 法å†ä½¿ç”¨ä»¥å‰ç‰ˆæœ¬çš„引擎打开项目。" #: editor/project_manager.cpp msgid "" "The project settings were created by a newer engine version, whose settings " "are not compatible with this version." -msgstr "" +msgstr "项目设置是由更新的引擎版本创建的,其设置与æ¤ç‰ˆæœ¬ä¸å…¼å®¹ã€‚" #: editor/project_manager.cpp msgid "" @@ -7825,15 +7846,15 @@ msgstr "å¤åˆ¶èŠ‚ç‚¹" #: editor/scene_tree_dock.cpp msgid "Can't reparent nodes in inherited scenes, order of nodes can't change." -msgstr "" +msgstr "æ— æ³•é‡æ–°è®¾ç½®ç»§æ‰¿åœºæ™¯ä¸çš„èŠ‚ç‚¹ï¼ŒèŠ‚ç‚¹é¡ºåºæ— 法更改。" #: editor/scene_tree_dock.cpp msgid "Node must belong to the edited scene to become root." -msgstr "" +msgstr "节点必须属于已编辑的场景æ‰èƒ½æˆä¸ºæ ¹èŠ‚ç‚¹ã€‚" #: editor/scene_tree_dock.cpp msgid "Instantiated scenes can't become root" -msgstr "" +msgstr "实例化的场景ä¸èƒ½æˆä¸ºæ ¹èŠ‚ç‚¹" #: editor/scene_tree_dock.cpp msgid "Delete Node(s)?" @@ -8634,10 +8655,6 @@ msgid "Build Project" msgstr "构建项目" #: modules/mono/editor/mono_bottom_panel.cpp -msgid "Warnings" -msgstr "è¦å‘Š" - -#: modules/mono/editor/mono_bottom_panel.cpp msgid "View log" msgstr "查看日志" @@ -9028,87 +9045,84 @@ msgstr "设值 %s" #: platform/android/export/export.cpp msgid "Package name is missing." -msgstr "" +msgstr "缺包å。" #: platform/android/export/export.cpp msgid "Package segments must be of non-zero length." -msgstr "" +msgstr "包段的长度必须为éžé›¶ã€‚" #: platform/android/export/export.cpp msgid "The character '%s' is not allowed in Android application package names." -msgstr "" +msgstr "Android应用程åºåŒ…åç§°ä¸ä¸å…许使用å—符“%sâ€ã€‚" #: platform/android/export/export.cpp msgid "A digit cannot be the first character in a package segment." -msgstr "" +msgstr "包段ä¸çš„第一个å—符ä¸èƒ½æ˜¯æ•°å—。" #: platform/android/export/export.cpp msgid "The character '%s' cannot be the first character in a package segment." -msgstr "" +msgstr "包段ä¸çš„第一个å—符ä¸èƒ½æ˜¯â€œ%sâ€ã€‚" #: platform/android/export/export.cpp msgid "The package must have at least one '.' separator." -msgstr "" +msgstr "包必须至少有一个“.â€åˆ†éš”符。" #: platform/android/export/export.cpp msgid "ADB executable not configured in the Editor Settings." -msgstr "" +msgstr "未在编辑器设置ä¸é…ç½®ADB坿‰§è¡Œæ–‡ä»¶ã€‚" #: platform/android/export/export.cpp msgid "OpenJDK jarsigner not configured in the Editor Settings." -msgstr "" +msgstr "未在编辑器设置ä¸é…ç½®OpenJDK Jarsigner。" #: platform/android/export/export.cpp msgid "Debug keystore not configured in the Editor Settings nor in the preset." -msgstr "" +msgstr "未在编辑器设置或预设ä¸é…置调试密钥库。" #: platform/android/export/export.cpp msgid "Invalid public key for APK expansion." -msgstr "" +msgstr "APKæ‰©å±•çš„å…¬é’¥æ— æ•ˆã€‚" #: platform/android/export/export.cpp -#, fuzzy msgid "Invalid package name:" -msgstr "ç±»åéžæ³•" +msgstr "æ— æ•ˆçš„åŒ…å称:" #: platform/iphone/export/export.cpp msgid "Identifier is missing." -msgstr "" +msgstr "ç¼ºå°‘æ ‡è¯†ç¬¦ã€‚" #: platform/iphone/export/export.cpp msgid "Identifier segments must be of non-zero length." -msgstr "" +msgstr "æ ‡è¯†ç¬¦å—æ®µä¸èƒ½ä¸ºç©º." #: platform/iphone/export/export.cpp -#, fuzzy msgid "The character '%s' is not allowed in Identifier." -msgstr "åç§°ä¸æ˜¯æœ‰æ•ˆçš„æ ‡è¯†ç¬¦ï¼š" +msgstr "æ ‡è¯†ç¬¦ä¸ä¸å…许使用å—符 '% s' 。" #: platform/iphone/export/export.cpp msgid "A digit cannot be the first character in a Identifier segment." -msgstr "" +msgstr "æ ‡è¯†ç¬¦æ®µä¸çš„第一个å—符ä¸èƒ½æ˜¯æ•°å—。" #: platform/iphone/export/export.cpp msgid "" "The character '%s' cannot be the first character in a Identifier segment." -msgstr "" +msgstr "æ ‡è¯†ç¬¦æ®µä¸çš„第一个å—符ä¸èƒ½æ˜¯\"%s\"。" #: platform/iphone/export/export.cpp msgid "The Identifier must have at least one '.' separator." -msgstr "" +msgstr "æ ‡è¯†ç¬¦å¿…é¡»è‡³å°‘æœ‰ä¸€ä¸ªâ€œ.â€åˆ†éš”符。" #: platform/iphone/export/export.cpp msgid "App Store Team ID not specified - cannot configure the project." -msgstr "" +msgstr "未指定应用商店团队ID-æ— æ³•é…置项目。" #: platform/iphone/export/export.cpp -#, fuzzy msgid "Invalid Identifier:" -msgstr "åç§°ä¸æ˜¯æœ‰æ•ˆçš„æ ‡è¯†ç¬¦ï¼š" +msgstr "æ— æ•ˆçš„æ ‡è¯†ç¬¦ï¼š" #: platform/iphone/export/export.cpp msgid "Required icon is not specified in the preset." -msgstr "" +msgstr "é¢„è®¾ä¸æœªæŒ‡å®šå¿…éœ€çš„å›¾æ ‡ã€‚" #: platform/javascript/export/export.cpp msgid "Run in Browser" @@ -9143,9 +9157,8 @@ msgid "Using default boot splash image." msgstr "使用默认å¯åŠ¨å›¾ç‰‡ã€‚" #: platform/uwp/export/export.cpp -#, fuzzy msgid "Invalid package unique name." -msgstr "åç§°éžæ³•。" +msgstr "包åå”¯ä¸€æ€§æ— æ•ˆã€‚" #: platform/uwp/export/export.cpp msgid "Invalid product GUID." @@ -9283,6 +9296,15 @@ msgid "" msgstr "" "ParallaxLayer类型的节点必须作为ParallaxBackgroundçš„å节点æ‰èƒ½æ£å¸¸å·¥ä½œã€‚" +#: scene/2d/particles_2d.cpp +msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles2D node instead. You can use the \"Convert to " +"CPUParticles\" option for this purpose." +msgstr "" +"基于GPU的粒åä¸å—GLES2视频驱动程åºçš„æ”¯æŒã€‚\n" +"改为使用CPUParticles2D节点。为æ¤ï¼Œæ‚¨å¯ä»¥ä½¿ç”¨â€œè½¬æ¢ä¸º CPUç²’åâ€é€‰é¡¹ã€‚" + #: scene/2d/particles_2d.cpp scene/3d/particles.cpp msgid "" "A material to process the particles is not assigned, so no behavior is " @@ -9451,6 +9473,15 @@ msgstr "" #: scene/3d/particles.cpp msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles node instead. You can use the \"Convert to CPUParticles" +"\" option for this purpose." +msgstr "" +"基于GPU的粒åä¸å—GLES2视频驱动程åºçš„æ”¯æŒã€‚\n" +"改为使用CPUParticles节点。为æ¤ï¼Œæ‚¨å¯ä»¥ä½¿ç”¨â€œè½¬æ¢ä¸º CPUç²’åâ€é€‰é¡¹ã€‚" + +#: scene/3d/particles.cpp +msgid "" "Nothing is visible because meshes have not been assigned to draw passes." msgstr "ç²’åä¸å¯è§ï¼Œå› ä¸ºæ²¡æœ‰ç½‘æ ¼(meshe)指定到绘制通é“(draw passes)。" @@ -9465,11 +9496,11 @@ msgid "PathFollow only works when set as a child of a Path node." msgstr "PathFollowç±»åž‹çš„èŠ‚ç‚¹åªæœ‰ä½œä¸ºPath类型节点的å节点æ‰èƒ½æ£å¸¸å·¥ä½œã€‚" #: scene/3d/path.cpp -#, fuzzy msgid "" "PathFollow ROTATION_ORIENTED requires \"Up Vector\" enabled in its parent " "Path's Curve resource." -msgstr "OrientedPathFollow 需è¦åœ¨å…¶çˆ¶è·¯å¾„ä¸å¯ç”¨â€œUp Vectorsâ€ã€‚" +msgstr "" +"PathFollow ROTATION_ORIENTED需è¦åœ¨å…¶çˆ¶è·¯å¾„的曲线资æºä¸å¯ç”¨â€œUp Vectorâ€ã€‚" #: scene/3d/physics_body.cpp msgid "" @@ -9485,23 +9516,6 @@ msgstr "" msgid "Path property must point to a valid Spatial node to work." msgstr "path属性必须指å‘ä¸€ä¸ªåˆæ³•çš„Spatial节点æ‰èƒ½æ£å¸¸å·¥ä½œã€‚" -#: scene/3d/scenario_fx.cpp -msgid "WorldEnvironment needs an Environment resource." -msgstr "WorldEnvironment需è¦ä¸€ä¸ªçŽ¯å¢ƒèµ„æºã€‚" - -#: scene/3d/scenario_fx.cpp -msgid "" -"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." -msgstr "æ¯ä¸ªåœºæ™¯ä¸åªå…许有一个WorldEnvironment类型的节点。" - -#: scene/3d/scenario_fx.cpp -msgid "" -"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " -"this environment's Background Mode to Canvas (for 2D scenes)." -msgstr "" -"这个WorldEnvironmentè¢«å¿½ç•¥ã€‚æ·»åŠ æ‘„åƒå¤´ï¼ˆç”¨äºŽ3D场景)或将æ¤çŽ¯å¢ƒçš„èƒŒæ™¯æ¨¡å¼è®¾ç½®" -"为画布(用于2D场景)。" - #: scene/3d/soft_body.cpp msgid "This body will be ignored until you set a mesh" msgstr "这个物体将被忽略,除éžè®¾ç½®ä¸€ä¸ªç½‘æ ¼" @@ -9531,6 +9545,23 @@ msgstr "" "VehicleWheel 为 VehicleBody æä¾›ä¸€ä¸ªè½¦è½®ç³»ç»Ÿï¼ˆWheel System)。请将它作为" "VehicleBodyçš„å节点。" +#: scene/3d/world_environment.cpp +msgid "WorldEnvironment needs an Environment resource." +msgstr "WorldEnvironment需è¦ä¸€ä¸ªçŽ¯å¢ƒèµ„æºã€‚" + +#: scene/3d/world_environment.cpp +msgid "" +"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." +msgstr "æ¯ä¸ªåœºæ™¯ä¸åªå…许有一个WorldEnvironment类型的节点。" + +#: scene/3d/world_environment.cpp +msgid "" +"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " +"this environment's Background Mode to Canvas (for 2D scenes)." +msgstr "" +"这个WorldEnvironmentè¢«å¿½ç•¥ã€‚æ·»åŠ æ‘„åƒå¤´ï¼ˆç”¨äºŽ3D场景)或将æ¤çŽ¯å¢ƒçš„èƒŒæ™¯æ¨¡å¼è®¾ç½®" +"为画布(用于2D场景)。" + #: scene/animation/animation_blend_tree.cpp msgid "On BlendTree node '%s', animation not found: '%s'" msgstr "在 BlendTree 节点 '%s' 上没有å‘现动画: '%s'" @@ -9572,11 +9603,20 @@ msgid "This node has been deprecated. Use AnimationTree instead." msgstr "这个节点已被弃用。请使用Animation Tree代替。" #: scene/gui/color_picker.cpp +msgid "Pick a color from the screen." +msgstr "从å±å¹•ä¸é€‰æ‹©ä¸€ç§é¢œè‰²ã€‚" + +#: scene/gui/color_picker.cpp msgid "Raw Mode" msgstr "Raw 模å¼" #: scene/gui/color_picker.cpp -msgid "Add current color as a preset" +msgid "Switch between hexadecimal and code values." +msgstr "在åå…进制值和代ç 值之间切æ¢ã€‚" + +#: scene/gui/color_picker.cpp +#, fuzzy +msgid "Add current color as a preset." msgstr "将当å‰é¢œè‰²æ·»åŠ ä¸ºé¢„è®¾" #: scene/gui/dialogs.cpp @@ -9666,6 +9706,18 @@ msgstr "对uniform的赋值。" msgid "Varyings can only be assigned in vertex function." msgstr "å˜é‡åªèƒ½åœ¨é¡¶ç‚¹å‡½æ•°ä¸æŒ‡å®šã€‚" +#~ msgid "Warnings:" +#~ msgstr "è¦å‘Šï¼š" + +#~ msgid "Font Size:" +#~ msgstr "å—体大å°:" + +#~ msgid "Line:" +#~ msgstr "行:" + +#~ msgid "Col:" +#~ msgstr "列:" + #~ msgid "OrientedPathFollow only works when set as a child of a Path node." #~ msgstr "" #~ "OrientedPathFollow ç±»åž‹çš„èŠ‚ç‚¹åªæœ‰ä½œä¸ºPath类型节点的å节点æ‰èƒ½æ£å¸¸å·¥ä½œã€‚" diff --git a/editor/translations/zh_HK.po b/editor/translations/zh_HK.po index 7b072a4123..6e72949b92 100644 --- a/editor/translations/zh_HK.po +++ b/editor/translations/zh_HK.po @@ -579,23 +579,14 @@ msgstr "縮å°" msgid "Reset Zoom" msgstr "é‡è¨ç¸®æ”¾æ¯”例" -#: editor/code_editor.cpp -msgid "Warnings:" +#: editor/code_editor.cpp modules/mono/editor/mono_bottom_panel.cpp +msgid "Warnings" msgstr "" #: editor/code_editor.cpp -msgid "Font Size:" +msgid "Line and column numbers." msgstr "" -#: editor/code_editor.cpp -#, fuzzy -msgid "Line:" -msgstr "行:" - -#: editor/code_editor.cpp -msgid "Col:" -msgstr "列:" - #: editor/connections_dialog.cpp msgid "Method in target Node must be specified!" msgstr "" @@ -900,8 +891,8 @@ msgstr "è¦åˆªé™¤é¸ä¸æª”案?" #: editor/dependency_editor.cpp editor/editor_audio_buses.cpp #: editor/editor_file_dialog.cpp editor/editor_node.cpp #: editor/filesystem_dock.cpp editor/plugins/item_list_editor_plugin.cpp -#: editor/project_export.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_dock.cpp +#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp +#: editor/project_settings_editor.cpp editor/scene_tree_dock.cpp msgid "Delete" msgstr "刪除" @@ -1175,7 +1166,7 @@ msgid "Add Bus" msgstr "" #: editor/editor_audio_buses.cpp -msgid "Create a new Bus Layout." +msgid "Add a new Audio Bus to this layout." msgstr "" #: editor/editor_audio_buses.cpp editor/editor_properties.cpp @@ -1206,6 +1197,10 @@ msgstr "é è¨" msgid "Load the default Bus Layout." msgstr "" +#: editor/editor_audio_buses.cpp +msgid "Create a new Bus Layout." +msgstr "" + #: editor/editor_autoload_settings.cpp msgid "Invalid name." msgstr "無效å稱" @@ -2470,7 +2465,7 @@ msgid "Save & Restart" msgstr "å„²å˜æª”案" #: editor/editor_node.cpp -msgid "Spins when the editor window repaints!" +msgid "Spins when the editor window redraws." msgstr "" #: editor/editor_node.cpp @@ -3590,24 +3585,6 @@ msgid "Create Polygon" msgstr "縮放selection" #: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Edit Polygon" -msgstr "æ’ä»¶" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Insert Point" -msgstr "" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Edit Polygon (Remove Point)" -msgstr "" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Remove Polygon And Point" -msgstr "åªé™é¸ä¸" - -#: editor/plugins/abstract_polygon_2d_editor.cpp #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #, fuzzy @@ -3627,6 +3604,24 @@ msgstr "" msgid "Erase points." msgstr "縮放selection" +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Edit Polygon" +msgstr "æ’ä»¶" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Insert Point" +msgstr "" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Edit Polygon (Remove Point)" +msgstr "" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Remove Polygon And Point" +msgstr "åªé™é¸ä¸" + #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #: editor/plugins/animation_player_editor_plugin.cpp @@ -4444,6 +4439,16 @@ msgid "Move CanvasItem" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp +msgid "Presets for the anchors and margins values of a Control node." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp +msgid "" +"Children of containers have their anchors and margins values overridden by " +"their parent." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp msgid "Anchors only" msgstr "" @@ -5361,6 +5366,12 @@ msgid "Create UV Map" msgstr "" #: editor/plugins/polygon_2d_editor_plugin.cpp +msgid "" +"Polygon 2D has internal vertices, so it can no longer be edited in the " +"viewport." +msgstr "" + +#: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Create Polygon & UV" msgstr "" @@ -6503,7 +6514,7 @@ msgid "Post" msgstr "" #: editor/plugins/spatial_editor_plugin.cpp -msgid "Name-less gizmo" +msgid "Nameless gizmo" msgstr "" #: editor/plugins/sprite_editor_plugin.cpp @@ -6584,8 +6595,14 @@ msgid "(empty)" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animations" -msgstr "" +#, fuzzy +msgid "Animations:" +msgstr "新增動畫" + +#: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "New Animation" +msgstr "新的動畫å稱:" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed (FPS):" @@ -6596,8 +6613,9 @@ msgid "Loop" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animation Frames" -msgstr "" +#, fuzzy +msgid "Animation Frames:" +msgstr "新的動畫å稱:" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Insert Empty (Before)" @@ -7430,6 +7448,19 @@ msgstr "" #: editor/project_manager.cpp msgid "" +"The following project settings file does not specify the version of Godot " +"through which it was created.\n" +"\n" +"%s\n" +"\n" +"If you proceed with opening it, it will be converted to Godot's current " +"configuration file format.\n" +"Warning: You will not be able to open the project with previous versions of " +"the engine anymore." +msgstr "" + +#: editor/project_manager.cpp +msgid "" "The following project settings file was generated by an older engine " "version, and needs to be converted for this version:\n" "\n" @@ -8977,10 +9008,6 @@ msgid "Build Project" msgstr "專案" #: modules/mono/editor/mono_bottom_panel.cpp -msgid "Warnings" -msgstr "" - -#: modules/mono/editor/mono_bottom_panel.cpp #, fuzzy msgid "View log" msgstr "檔案" @@ -9638,6 +9665,13 @@ msgid "" "ParallaxLayer node only works when set as child of a ParallaxBackground node." msgstr "" +#: scene/2d/particles_2d.cpp +msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles2D node instead. You can use the \"Convert to " +"CPUParticles\" option for this purpose." +msgstr "" + #: scene/2d/particles_2d.cpp scene/3d/particles.cpp msgid "" "A material to process the particles is not assigned, so no behavior is " @@ -9793,6 +9827,13 @@ msgstr "" #: scene/3d/particles.cpp msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles node instead. You can use the \"Convert to CPUParticles" +"\" option for this purpose." +msgstr "" + +#: scene/3d/particles.cpp +msgid "" "Nothing is visible because meshes have not been assigned to draw passes." msgstr "" @@ -9823,21 +9864,6 @@ msgstr "" msgid "Path property must point to a valid Spatial node to work." msgstr "" -#: scene/3d/scenario_fx.cpp -msgid "WorldEnvironment needs an Environment resource." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " -"this environment's Background Mode to Canvas (for 2D scenes)." -msgstr "" - #: scene/3d/soft_body.cpp msgid "This body will be ignored until you set a mesh" msgstr "" @@ -9861,6 +9887,21 @@ msgid "" "it as a child of a VehicleBody." msgstr "" +#: scene/3d/world_environment.cpp +msgid "WorldEnvironment needs an Environment resource." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " +"this environment's Background Mode to Canvas (for 2D scenes)." +msgstr "" + #: scene/animation/animation_blend_tree.cpp msgid "On BlendTree node '%s', animation not found: '%s'" msgstr "" @@ -9906,11 +9947,19 @@ msgid "This node has been deprecated. Use AnimationTree instead." msgstr "" #: scene/gui/color_picker.cpp +msgid "Pick a color from the screen." +msgstr "" + +#: scene/gui/color_picker.cpp msgid "Raw Mode" msgstr "" #: scene/gui/color_picker.cpp -msgid "Add current color as a preset" +msgid "Switch between hexadecimal and code values." +msgstr "" + +#: scene/gui/color_picker.cpp +msgid "Add current color as a preset." msgstr "" #: scene/gui/dialogs.cpp @@ -9995,6 +10044,13 @@ msgid "Varyings can only be assigned in vertex function." msgstr "" #, fuzzy +#~ msgid "Line:" +#~ msgstr "行:" + +#~ msgid "Col:" +#~ msgstr "列:" + +#, fuzzy #~ msgid "Split already exists." #~ msgstr "AutoLoad '%s'å·²å˜åœ¨ï¼" diff --git a/editor/translations/zh_TW.po b/editor/translations/zh_TW.po index 58c3085900..4d9b3b578f 100644 --- a/editor/translations/zh_TW.po +++ b/editor/translations/zh_TW.po @@ -12,12 +12,13 @@ # Qing <icinriiq@gmail.com>, 2018. # Sam Pan <sampan66@gmail.com>, 2016. # ken l <macauhome@gmail.com>, 2018. +# Eric K <eric900601@gmail.com>, 2019. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2018-12-13 14:44+0100\n" -"Last-Translator: ken l <macauhome@gmail.com>\n" +"PO-Revision-Date: 2019-02-01 12:09+0000\n" +"Last-Translator: Eric K <eric900601@gmail.com>\n" "Language-Team: Chinese (Traditional) <https://hosted.weblate.org/projects/" "godot-engine/godot/zh_Hant/>\n" "Language: zh_TW\n" @@ -25,34 +26,35 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Poedit 2.2\n" +"X-Generator: Weblate 3.5-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp msgid "Invalid type argument to convert(), use TYPE_* constants." -msgstr "" +msgstr "Convert()å‡½æ•¸æ‰€æ”¶åˆ°çš„åƒæ•¸éŒ¯èª¤ï¼Œè«‹è©¦è‘—以 TYPE_ 作為開é 。" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/mono/glue/gd_glue.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp msgid "Not enough bytes for decoding bytes, or invalid format." -msgstr "解碼å—節ä½å…ƒä¸è¶³ï¼Œæˆ–ç‚ºç„¡æ•ˆæ ¼å¼ã€‚" +msgstr "輸入的解碼å—節ä¸è¶³ã€æˆ–ç‚ºç„¡æ•ˆæ ¼å¼ã€‚" #: core/math/expression.cpp +#, fuzzy msgid "Invalid input %i (not passed) in expression" -msgstr "" +msgstr "所輸入的 %i 於表ç¾å¼ä¸ç„¡æ•ˆ" #: core/math/expression.cpp msgid "self can't be used because instance is null (not passed)" -msgstr "" +msgstr "å› è©²å¯¦ä¾‹(instance)為空,self 無法被使用" #: core/math/expression.cpp msgid "Invalid operands to operator %s, %s and %s." -msgstr "" +msgstr "æ¤æ•¸å€¼ç„¡æ³•被 %sã€%s å’Œ %s é‹ç®—。" #: core/math/expression.cpp msgid "Invalid index of type %s for base type %s" -msgstr "" +msgstr "無效的內å˜åœ°å€é¡žåž‹ %sï¼ŒåŸºç¤Žåž‹å¼ %s" #: core/math/expression.cpp msgid "Invalid named index '%s' for base type %s" @@ -80,47 +82,44 @@ msgid "Mirror" msgstr "" #: editor/animation_bezier_editor.cpp -#, fuzzy msgid "Insert Key Here" -msgstr "動畫新增按éµ" +msgstr "åœ¨æ¤æ’å…¥ç•«æ ¼" #: editor/animation_bezier_editor.cpp -#, fuzzy msgid "Duplicate Selected Key(s)" -msgstr "複製所é¸" +msgstr "複製所é¸ç•«æ ¼" #: editor/animation_bezier_editor.cpp -#, fuzzy msgid "Delete Selected Key(s)" -msgstr "ç¢ºå®šåˆªé™¤æ‰€é¸æ“‡çš„æª”案嗎?" +msgstr "刪除所é¸ç•«æ ¼" #: editor/animation_bezier_editor.cpp editor/animation_track_editor.cpp msgid "Anim Duplicate Keys" -msgstr "複製動畫關éµç•«æ ¼" +msgstr "複製關éµç•«æ ¼" #: editor/animation_bezier_editor.cpp editor/animation_track_editor.cpp msgid "Anim Delete Keys" -msgstr "刪除動畫關éµç•«æ ¼" +msgstr "刪除關éµç•«æ ¼" #: editor/animation_track_editor.cpp msgid "Anim Change Keyframe Time" -msgstr "動畫更改關éµå¹€æ™‚é–“" +msgstr "變更關éµç•«æ ¼çš„æ™‚é–“" #: editor/animation_track_editor.cpp msgid "Anim Change Transition" -msgstr "å‹•ç•«æ›´æ”¹è½‰å ´æ•ˆæžœ" +msgstr "è®Šæ›´è½‰å ´æ•ˆæžœ" #: editor/animation_track_editor.cpp msgid "Anim Change Transform" -msgstr "動畫更改座標" +msgstr "變更動畫變æ›" #: editor/animation_track_editor.cpp msgid "Anim Change Keyframe Value" -msgstr "動畫更改關éµå¹€æ•¸å€¼" +msgstr "變更關éµç•«æ ¼çš„æ•¸å€¼" #: editor/animation_track_editor.cpp msgid "Anim Change Call" -msgstr "動畫更改呼å«" +msgstr "更改回調" #: editor/animation_track_editor.cpp msgid "Property Track" @@ -152,9 +151,8 @@ msgid "Add Track" msgstr "æ·»åŠ å‹•ç•«è»Œ" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Animation Length Time (seconds)" -msgstr "動畫長度 (ç§’)。" +msgstr "動畫長度(秒)" #: editor/animation_track_editor.cpp #, fuzzy @@ -258,11 +256,11 @@ msgstr "刪除動畫軌" #: editor/animation_track_editor.cpp msgid "Create NEW track for %s and insert key?" -msgstr "%s 新增新軌並æ’å…¥ç•«æ ¼?" +msgstr "為 %s 新增動畫軌並æ’å…¥ç•«æ ¼ï¼Ÿ" #: editor/animation_track_editor.cpp msgid "Create %d NEW tracks and insert keys?" -msgstr "創建 %d 個新軌並æ’å…¥ç•«æ ¼?" +msgstr "創建 %d 個動畫軌並æ’å…¥ç•«æ ¼ï¼Ÿ" #: editor/animation_track_editor.cpp editor/create_dialog.cpp #: editor/editor_audio_buses.cpp editor/editor_plugin_settings.cpp @@ -283,7 +281,7 @@ msgstr "" #: editor/animation_track_editor.cpp msgid "Anim Create & Insert" -msgstr "動畫建立與æ’å…¥" +msgstr "新增/æ’入動畫" #: editor/animation_track_editor.cpp #, fuzzy @@ -292,7 +290,7 @@ msgstr "動畫新增軌跡與按éµ" #: editor/animation_track_editor.cpp msgid "Anim Insert Key" -msgstr "動畫新增按éµ" +msgstr "新增關éµç•«æ ¼" #: editor/animation_track_editor.cpp msgid "Transform tracks only apply to Spatial-based nodes." @@ -336,7 +334,7 @@ msgstr "" #: editor/animation_track_editor.cpp msgid "Anim Move Keys" -msgstr "ç§»å‹•å‹•ç•«ç•«æ ¼" +msgstr "移動關éµç•«æ ¼" #: editor/animation_track_editor.cpp msgid "Clipboard is empty" @@ -399,7 +397,7 @@ msgstr "縮放所é¸" #: editor/animation_track_editor.cpp msgid "Scale From Cursor" -msgstr "由游標ä½ç½®ç¸®æ”¾" +msgstr "由游標縮放" #: editor/animation_track_editor.cpp modules/gridmap/grid_map_editor_plugin.cpp msgid "Duplicate Selection" @@ -407,7 +405,7 @@ msgstr "複製所é¸" #: editor/animation_track_editor.cpp msgid "Duplicate Transposed" -msgstr "é‡è¤‡è½‰ç½®" +msgstr "複製並轉置" #: editor/animation_track_editor.cpp #, fuzzy @@ -426,7 +424,7 @@ msgstr "往上一æ¥" #: editor/animation_track_editor.cpp msgid "Optimize Animation" -msgstr "最佳化動畫" +msgstr "動畫最佳化" #: editor/animation_track_editor.cpp msgid "Clean-Up Animation" @@ -463,11 +461,11 @@ msgstr "最佳化" #: editor/animation_track_editor.cpp msgid "Remove invalid keys" -msgstr "移除無效按éµ" +msgstr "移除無效的關éµç•«æ ¼" #: editor/animation_track_editor.cpp msgid "Remove unresolved and empty tracks" -msgstr "刪除未解決或是空的軌é“" +msgstr "刪除未處ç†çš„空白軌é“" #: editor/animation_track_editor.cpp msgid "Clean-up all animations" @@ -475,7 +473,7 @@ msgstr "清除所有動畫" #: editor/animation_track_editor.cpp msgid "Clean-Up Animation(s) (NO UNDO!)" -msgstr "清除動畫 (無法復原!)" +msgstr "永久刪除動畫(無法復原ï¼ï¼‰" #: editor/animation_track_editor.cpp msgid "Clean-Up" @@ -523,7 +521,7 @@ msgstr "ç„¡ç¬¦åˆæ¢ä»¶" #: editor/code_editor.cpp msgid "Replaced %d occurrence(s)." -msgstr "å–代了 %d 個" +msgstr "å–代了 %d 個。" #: editor/code_editor.cpp editor/find_in_files.cpp msgid "Match Case" @@ -531,7 +529,7 @@ msgstr "符åˆå¤§å°å¯«" #: editor/code_editor.cpp editor/find_in_files.cpp msgid "Whole Words" -msgstr "整個å—" +msgstr "符åˆå®Œæ•´å–®å—" #: editor/code_editor.cpp editor/rename_dialog.cpp msgid "Replace" @@ -561,31 +559,23 @@ msgstr "縮å°" msgid "Reset Zoom" msgstr "é‡è¨ç¸®æ”¾å¤§å°" -#: editor/code_editor.cpp -msgid "Warnings:" +#: editor/code_editor.cpp modules/mono/editor/mono_bottom_panel.cpp +msgid "Warnings" msgstr "" #: editor/code_editor.cpp -msgid "Font Size:" +msgid "Line and column numbers." msgstr "" -#: editor/code_editor.cpp -msgid "Line:" -msgstr "行:" - -#: editor/code_editor.cpp -msgid "Col:" -msgstr "列:" - #: editor/connections_dialog.cpp msgid "Method in target Node must be specified!" -msgstr "需指定在目標節點上的方法!" +msgstr "å¿…é ˆæŒ‡å®šå°ç›®æ¨™ç¯€é»žçš„行為ï¼" #: editor/connections_dialog.cpp msgid "" "Target method not found! Specify a valid method or attach a script to target " "Node." -msgstr "找ä¸åˆ°ç›®æ¨™æ–¹æ³•! 指定一個å°çš„æ–¹æ³•æˆ–é™„åŠ ä¸€å€‹è…³æœ¬åˆ°ç›®æ¨™çš„ç¯€é»žä¸Šã€‚" +msgstr "找ä¸åˆ°ç›®æ¨™æ–¹æ³•ï¼è«‹æŒ‡å®šæœ‰æ•ˆæ–¹æ³•ã€æˆ–å°‡è…³æœ¬é™„åŠ è‡³ç›®æ¨™ç¯€é»žä¸Šã€‚" #: editor/connections_dialog.cpp msgid "Connect To Node:" @@ -881,8 +871,8 @@ msgstr "ç¢ºå®šåˆªé™¤æ‰€é¸æ“‡çš„æª”案嗎?" #: editor/dependency_editor.cpp editor/editor_audio_buses.cpp #: editor/editor_file_dialog.cpp editor/editor_node.cpp #: editor/filesystem_dock.cpp editor/plugins/item_list_editor_plugin.cpp -#: editor/project_export.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_dock.cpp +#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp +#: editor/project_settings_editor.cpp editor/scene_tree_dock.cpp msgid "Delete" msgstr "刪除" @@ -1150,8 +1140,9 @@ msgid "Add Bus" msgstr "新增 Bus" #: editor/editor_audio_buses.cpp -msgid "Create a new Bus Layout." -msgstr "建立新的 Bus é…置。" +#, fuzzy +msgid "Add a new Audio Bus to this layout." +msgstr "å¦å˜ Audio Bus é…置為..." #: editor/editor_audio_buses.cpp editor/editor_properties.cpp #: editor/plugins/animation_player_editor_plugin.cpp editor/property_editor.cpp @@ -1179,6 +1170,10 @@ msgstr "載入é è¨å€¼" msgid "Load the default Bus Layout." msgstr "載入é è¨çš„ Bus é…置。" +#: editor/editor_audio_buses.cpp +msgid "Create a new Bus Layout." +msgstr "建立新的 Bus é…置。" + #: editor/editor_autoload_settings.cpp msgid "Invalid name." msgstr "ä¸èƒ½ä½¿ç”¨çš„å稱。" @@ -1869,7 +1864,7 @@ msgstr "" #: editor/editor_node.cpp msgid "Current scene was never saved, please save it prior to running." -msgstr "è«‹å…ˆå˜æª”æ‰èƒ½åŸ·è¡Œè©²å ´æ™¯" +msgstr "在é‹è¡Œå ´æ™¯å‰ï¼Œè«‹å…ˆå˜æª”。" #: editor/editor_node.cpp msgid "Could not start subprocess!" @@ -1906,7 +1901,7 @@ msgstr "å¦å˜å ´æ™¯ç‚º..." #: editor/editor_node.cpp msgid "No" -msgstr "" +msgstr "䏿˜¯" #: editor/editor_node.cpp msgid "Yes" @@ -1918,7 +1913,7 @@ msgstr "æ¤å ´æ™¯å°šæœªå˜æª”, 執行å‰è«‹å…ˆå˜æª”" #: editor/editor_node.cpp editor/scene_tree_dock.cpp msgid "This operation can't be done without a scene." -msgstr "" +msgstr "在è¨ç½®å ´æ™¯å‰ï¼Œç„¡æ³•完æˆè©²æŒ‡å®šæ“作。" #: editor/editor_node.cpp msgid "Export Mesh Library" @@ -1926,20 +1921,19 @@ msgstr "" #: editor/editor_node.cpp msgid "This operation can't be done without a root node." -msgstr "æ¤æ“ä½œç„¡æ³•åœ¨æ²’æœ‰æ ¹ç¯€é»žçš„æƒ…æ³ä¸‹é€²è¡Œã€‚" +msgstr "在è¨ç½®æ ¹ç¯€é»ž(root node)å‰ï¼Œç„¡æ³•完æˆè©²æŒ‡å®šæ“作。" #: editor/editor_node.cpp msgid "Export Tile Set" msgstr "" #: editor/editor_node.cpp -#, fuzzy msgid "This operation can't be done without a selected node." -msgstr "æ¤æ“ä½œéœ€è¦æœ‰é¸æ“‡è‘—節點æ‰èƒ½é€²è¡Œã€‚" +msgstr "在è¨ç½®è‘—節點(selected node)å‰ï¼Œç„¡æ³•完æˆè©²æŒ‡å®šæ“作。" #: editor/editor_node.cpp msgid "Current scene not saved. Open anyway?" -msgstr "ç›®å‰çš„å ´æ™¯å°šæœªå˜æª”, ä¾ç„¶è¦é–‹å•Ÿå—Ž?" +msgstr "ç›®å‰çš„å ´æ™¯å°šæœªå˜æª”,ä»è¦é–‹å•Ÿå—Žï¼Ÿ" #: editor/editor_node.cpp msgid "Can't reload a scene that was never saved." @@ -1950,12 +1944,13 @@ msgid "Revert" msgstr "還原" #: editor/editor_node.cpp +#, fuzzy msgid "This action cannot be undone. Revert anyway?" -msgstr "æ¤æ“作無法復原, 確定è¦é‚„原嗎?" +msgstr "æ¤æ“作無法被, 確定è¦é‚„原嗎?" #: editor/editor_node.cpp msgid "Quick Run Scene..." -msgstr "å¿«é€ŸåŸ·è¡Œå ´æ™¯..." +msgstr "å¿«é€ŸåŸ·è¡Œå ´æ™¯â€¦" #: editor/editor_node.cpp msgid "Quit" @@ -1963,89 +1958,93 @@ msgstr "離開" #: editor/editor_node.cpp msgid "Exit the editor?" -msgstr "離開編輯器嗎?" +msgstr "è¦çµæŸç·¨è¼¯å™¨å—Žï¼Ÿ" #: editor/editor_node.cpp msgid "Open Project Manager?" -msgstr "" +msgstr "è¦é–‹å•Ÿå°ˆæ¡ˆç®¡ç†å—Žï¼Ÿ" #: editor/editor_node.cpp msgid "Save & Quit" -msgstr "" +msgstr "儲å˜ä¸¦é›¢é–‹" #: editor/editor_node.cpp msgid "Save changes to the following scene(s) before quitting?" -msgstr "" +msgstr "關閉å‰ï¼Œè¦å„²å˜ä¿®æ”¹çš„å ´æ™¯å—Žï¼Ÿ" #: editor/editor_node.cpp msgid "Save changes the following scene(s) before opening Project Manager?" -msgstr "" +msgstr "開啟專案管ç†å‰ï¼Œè¦å„²å˜ä¿®æ”¹çš„å ´æ™¯å—Žï¼Ÿ" #: editor/editor_node.cpp msgid "" "This option is deprecated. Situations where refresh must be forced are now " "considered a bug. Please report." -msgstr "" +msgstr "ä¸æŽ¨è–¦æ¤é¸é …ã€‚è¢«å¼·åˆ¶é‡æ–°æ•´ç†çš„æƒ…形,å¯èƒ½æ˜¯å› 程å¼éŒ¯èª¤å°Žè‡´ã€‚è«‹å›žå ±ã€‚" #: editor/editor_node.cpp msgid "Pick a Main Scene" -msgstr "挑一個主è¦å ´æ™¯" +msgstr "é¸å–一個主è¦å ´æ™¯" #: editor/editor_node.cpp msgid "Unable to enable addon plugin at: '%s' parsing of config failed." -msgstr "" +msgstr "無法在: \"%s\" 上啟動擴充功能,è¨å®šè§£æžå¤±æ•—。" #: editor/editor_node.cpp msgid "Unable to find script field for addon plugin at: 'res://addons/%s'." -msgstr "" +msgstr "在æ’件目錄 'res://addons/%s' ä¸ï¼Œæ‰¾ä¸åˆ°è…³æœ¬ã€‚" #: editor/editor_node.cpp msgid "Unable to load addon script from path: '%s'." -msgstr "" +msgstr "無法從 '%s' ä¸é †åˆ©è®€å–腳本。" #: editor/editor_node.cpp msgid "" "Unable to load addon script from path: '%s' There seems to be an error in " "the code, please check the syntax." -msgstr "" +msgstr "無法從 '%s' ä¸é †åˆ©è®€å–腳本。å¯èƒ½å‡ºè‡ªç·¨ç¢¼éŒ¯èª¤ï¼Œè«‹æª¢å¯Ÿèªžæ³•æ˜¯å¦æ£ç¢ºã€‚" #: editor/editor_node.cpp msgid "" "Unable to load addon script from path: '%s' Base type is not EditorPlugin." -msgstr "" +msgstr "無法從 '%s' ä¸é †åˆ©è®€å–腳本。基本類型 的腳本並ä¸å±¬æ–¼ 編輯類æ’件。" #: editor/editor_node.cpp msgid "Unable to load addon script from path: '%s' Script is not in tool mode." -msgstr "" +msgstr "無法從 '%s' ä¸é †åˆ©è®€å–腳本。æ¤è…³æœ¬ä¸¦ä¸è™•於工具模å¼ä¸‹ã€‚" #: editor/editor_node.cpp msgid "" "Scene '%s' was automatically imported, so it can't be modified.\n" "To make changes to it, a new inherited scene can be created." msgstr "" +"å ´æ™¯\"%s\"為自動導入,並ä¸èƒ½è¢«ä¿®æ”¹ã€‚\n" +"è‹¥è¦é€²è¡Œæ›´æ”¹ï¼Œè«‹å»ºç«‹æ–°çš„å ´æ™¯ã€‚" #: editor/editor_node.cpp msgid "" "Error loading scene, it must be inside the project path. Use 'Import' to " "open the scene, then save it inside the project path." msgstr "" +"讀å–å ´æ™¯æ™‚ç™¼ç”ŸéŒ¯èª¤ï¼Œå ´æ™¯å¿…é ˆæ”¾ç½®æ–¼å°ˆæ¡ˆè³‡æ–™å¤¾å…§ã€‚è«‹ç”¨ã€Œå°Žå…¥ã€é–‹å•Ÿè©²å ´æ™¯å¾Œï¼Œå†" +"å„²å˜æ–¼å°ˆæ¡ˆè³‡æ–™å¤¾ã€‚" #: editor/editor_node.cpp +#, fuzzy msgid "Scene '%s' has broken dependencies:" -msgstr "" +msgstr "å ´æ™¯ '%s' çš„ä¾å˜é—œä¿‚å·²è¢«ç ´å£žã€‚" #: editor/editor_node.cpp -#, fuzzy msgid "Clear Recent Scenes" -msgstr "é—œé–‰å ´æ™¯" +msgstr "æ¸…é™¤æœ€è¿‘é–‹å•Ÿçš„å ´æ™¯" #: editor/editor_node.cpp msgid "Save Layout" -msgstr "" +msgstr "儲å˜ä½ˆå±€" #: editor/editor_node.cpp msgid "Delete Layout" -msgstr "" +msgstr "刪除佈局" #: editor/editor_node.cpp editor/import_dock.cpp #: editor/script_create_dialog.cpp @@ -2054,28 +2053,24 @@ msgstr "é è¨" #: editor/editor_node.cpp editor/editor_properties.cpp #: editor/plugins/script_editor_plugin.cpp editor/property_editor.cpp -#, fuzzy msgid "Show in FileSystem" -msgstr "在檔案管ç†å“¡å…§é¡¯ç¤º" +msgstr "在檔案系統ä¸é¡¯ç¤º" #: editor/editor_node.cpp -#, fuzzy msgid "Play This Scene" -msgstr "æš«åœå ´æ™¯" +msgstr "é‹è¡Œæ¤å ´æ™¯" #: editor/editor_node.cpp -#, fuzzy msgid "Close Tab" -msgstr "關閉" +msgstr "關閉分é " #: editor/editor_node.cpp msgid "Switch Scene Tab" msgstr "切æ›å ´æ™¯åˆ†é " #: editor/editor_node.cpp -#, fuzzy msgid "%d more files or folders" -msgstr "還有 %d 個檔案或資料夾" +msgstr "還有 %d 個檔案/資料夾" #: editor/editor_node.cpp #, fuzzy @@ -2083,26 +2078,24 @@ msgid "%d more folders" msgstr "還有 %d 個檔案" #: editor/editor_node.cpp -#, fuzzy msgid "%d more files" msgstr "還有 %d 個檔案" #: editor/editor_node.cpp msgid "Dock Position" -msgstr "" +msgstr "版é¢ä½ç½®" #: editor/editor_node.cpp msgid "Distraction Free Mode" -msgstr "" +msgstr "無干擾模å¼" #: editor/editor_node.cpp msgid "Toggle distraction-free mode." -msgstr "" +msgstr "切æ›ç‚ºç„¡å¹²æ“¾æ¨¡å¼ã€‚" #: editor/editor_node.cpp -#, fuzzy msgid "Add a new scene." -msgstr "æ›´æ–°å ´æ™¯ä¸..." +msgstr "æ–°å¢žå ´æ™¯ã€‚" #: editor/editor_node.cpp #, fuzzy @@ -2111,35 +2104,35 @@ msgstr "å ´æ™¯" #: editor/editor_node.cpp msgid "Go to previously opened scene." -msgstr "" +msgstr "å‰å¾€ä¸Šæ¬¡é–‹å•Ÿçš„å ´æ™¯ã€‚" #: editor/editor_node.cpp msgid "Next tab" -msgstr "下個分é " +msgstr "下一個分é " #: editor/editor_node.cpp msgid "Previous tab" -msgstr "上個分é " +msgstr "上一個分é " #: editor/editor_node.cpp msgid "Filter Files..." -msgstr "éŽæ¿¾æª”案..." +msgstr "ç¯©é¸æª”案..." #: editor/editor_node.cpp msgid "Operations with scene files." -msgstr "" +msgstr "æ“ä½œå ´æ™¯æ–‡ä»¶ã€‚" #: editor/editor_node.cpp msgid "New Scene" -msgstr "" +msgstr "æ–°å ´æ™¯" #: editor/editor_node.cpp msgid "New Inherited Scene..." -msgstr "" +msgstr "å¾žç¾æœ‰å ´æ™¯ä¸å»ºç«‹â€¦" #: editor/editor_node.cpp msgid "Open Scene..." -msgstr "é–‹å•Ÿå ´æ™¯..." +msgstr "é–‹å•Ÿå ´æ™¯â€¦" #: editor/editor_node.cpp msgid "Save Scene" @@ -2156,42 +2149,41 @@ msgstr "é—œé–‰å ´æ™¯" #: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp msgid "Open Recent" -msgstr "開啟最近å˜å–" +msgstr "æœ€è¿‘é–‹å•Ÿçš„å ´æ™¯" #: editor/editor_node.cpp msgid "Convert To..." -msgstr "è½‰æ›æˆ..." +msgstr "è½‰æ›æˆâ€¦" #: editor/editor_node.cpp msgid "MeshLibrary..." -msgstr "" +msgstr "網狀資料庫(MeshLibrary)…" #: editor/editor_node.cpp msgid "TileSet..." -msgstr "" +msgstr "å€å¡Šç´ æâ€¦" #: editor/editor_node.cpp editor/plugins/script_text_editor.cpp #: scene/gui/line_edit.cpp scene/gui/text_edit.cpp msgid "Undo" -msgstr "復原" +msgstr "還原" #: editor/editor_node.cpp editor/plugins/script_text_editor.cpp #: scene/gui/line_edit.cpp scene/gui/text_edit.cpp msgid "Redo" -msgstr "å–æ¶ˆã€Œå¾©åŽŸã€" +msgstr "é‡ä½œ" #: editor/editor_node.cpp msgid "Revert Scene" -msgstr "" +msgstr "æ¢å¾©å ´æ™¯" #: editor/editor_node.cpp msgid "Miscellaneous project or scene-wide tools." -msgstr "" +msgstr "其他專案或全螢幕工具。" #: editor/editor_node.cpp -#, fuzzy msgid "Project" -msgstr "專案è¨å®š" +msgstr "專案" #: editor/editor_node.cpp msgid "Project Settings" @@ -2206,32 +2198,31 @@ msgid "Tools" msgstr "工具" #: editor/editor_node.cpp -#, fuzzy msgid "Open Project Data Folder" -msgstr "專案創始人" +msgstr "開啟專案資料夾" #: editor/editor_node.cpp msgid "Quit to Project List" -msgstr "" +msgstr "退出到專案列表" #: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp #: editor/project_export.cpp msgid "Debug" -msgstr "" +msgstr "åµéŒ¯" #: editor/editor_node.cpp msgid "Deploy with Remote Debug" -msgstr "" +msgstr "使用é 端åµéŒ¯" #: editor/editor_node.cpp msgid "" "When exporting or deploying, the resulting executable will attempt to " "connect to the IP of this computer in order to be debugged." -msgstr "" +msgstr "當輸出或發布專案後,å¯åŸ·è¡Œæ–‡ä»¶(exe)å°‡æœƒå˜—è©¦é€£çµæœ¬æ©Ÿï¼©ï¼°ï¼Œä»¥é€²è¡ŒåµéŒ¯ã€‚" #: editor/editor_node.cpp msgid "Small Deploy with Network FS" -msgstr "" +msgstr "å°åž‹éƒ¨å±¬ & 網路文件系統(NFS)" #: editor/editor_node.cpp msgid "" @@ -2242,30 +2233,34 @@ msgid "" "On Android, deploy will use the USB cable for faster performance. This " "option speeds up testing for games with a large footprint." msgstr "" +"啟用æ¤é¸é …後,在輸出/ç™¼å¸ƒé …ç›®æ™‚ï¼ŒåŸ·è¡Œæª”æœƒå£“ç¸®è‡³æœ€å°ã€‚\n" +"至於文件系統,則以網路與編輯器的連çµä¾†ä¾›çµ¦ã€‚\n" +"在Androidå¹³å°ï¼Œé€éŽUSB發布能ç²å¾—更快的效率。\n" +"æ¤é¸é …ç”¨æ–¼åŠ é€ŸéŠæˆ²(尤其是檔案ç¹å¤š)的測試。" #: editor/editor_node.cpp msgid "Visible Collision Shapes" -msgstr "" +msgstr "碰撞å€åŸŸçš„顯示" #: editor/editor_node.cpp msgid "" "Collision shapes and raycast nodes (for 2D and 3D) will be visible on the " "running game if this option is turned on." -msgstr "" +msgstr "啟用æ¤é¸é …後,碰撞å€åŸŸ/射線節點 å°‡æœƒæ–¼éŠæˆ²ä¸é¡¯ç¤ºã€‚" #: editor/editor_node.cpp msgid "Visible Navigation" -msgstr "" +msgstr "導航的顯示" #: editor/editor_node.cpp msgid "" "Navigation meshes and polygons will be visible on the running game if this " "option is turned on." -msgstr "" +msgstr "啟用æ¤é¸é …後,導航所用的網線/多邊形 å°‡æœƒæ–¼éŠæˆ²ä¸é¡¯ç¤ºã€‚" #: editor/editor_node.cpp msgid "Sync Scene Changes" -msgstr "" +msgstr "åŒæ¥å ´æ™¯çš„變更" #: editor/editor_node.cpp msgid "" @@ -2274,10 +2269,12 @@ msgid "" "When used remotely on a device, this is more efficient with network " "filesystem." msgstr "" +"啟用æ¤é¸é …後,編輯器ä¸çš„æ‰€æœ‰ä¿®æ”¹ï¼Œéƒ½æœƒç«‹å³åæ˜ æ–¼é‹è¡Œä¸çš„éŠæˆ²ã€‚\n" +"在é 端è£ç½®æ¸¬è©¦æ™‚,é…åˆç¶²è·¯æ–‡ä»¶ç³»çµ±(NFS)使用能更æé«˜æ•ˆçŽ‡ã€‚" #: editor/editor_node.cpp msgid "Sync Script Changes" -msgstr "" +msgstr "åŒæ¥è…³æœ¬çš„變更" #: editor/editor_node.cpp msgid "" @@ -2286,42 +2283,44 @@ msgid "" "When used remotely on a device, this is more efficient with network " "filesystem." msgstr "" +"啟用æ¤é¸é …後,腳本的所有修改,都會立å³åæ˜ æ–¼é‹è¡Œä¸çš„éŠæˆ²ã€‚\n" +"在é 端è£ç½®æ¸¬è©¦æ™‚,é…åˆç¶²è·¯æ–‡ä»¶ç³»çµ±(NFS)使用能更æé«˜æ•ˆçŽ‡ã€‚" #: editor/editor_node.cpp msgid "Editor" -msgstr "" +msgstr "編輯器" #: editor/editor_node.cpp editor/settings_config_dialog.cpp msgid "Editor Settings" -msgstr "" +msgstr "編輯器è¨å®š" #: editor/editor_node.cpp msgid "Editor Layout" -msgstr "" +msgstr "編輯器佈局" #: editor/editor_node.cpp msgid "Toggle Fullscreen" -msgstr "" +msgstr "全螢幕顯示" #: editor/editor_node.cpp msgid "Open Editor Data/Settings Folder" -msgstr "" +msgstr "開啟 編輯器數據/è¨å®š 資料夾" #: editor/editor_node.cpp msgid "Open Editor Data Folder" -msgstr "" +msgstr "開啟 編輯器數據 資料夾" #: editor/editor_node.cpp msgid "Open Editor Settings Folder" -msgstr "" +msgstr "開啟 編輯器è¨å®š 資料夾" #: editor/editor_node.cpp editor/project_export.cpp msgid "Manage Export Templates" -msgstr "" +msgstr "管ç†è¼¸å‡ºæ¨¡æ¿" #: editor/editor_node.cpp msgid "Help" -msgstr "" +msgstr "幫助" #: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp #: editor/plugins/script_editor_plugin.cpp @@ -2333,15 +2332,16 @@ msgstr "æœå°‹" #: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp msgid "Online Docs" -msgstr "" +msgstr "線上文件" #: editor/editor_node.cpp msgid "Q&A" -msgstr "" +msgstr "Q&A" #: editor/editor_node.cpp +#, fuzzy msgid "Issue Tracker" -msgstr "" +msgstr "å•題追蹤器" #: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp msgid "Community" @@ -2353,11 +2353,11 @@ msgstr "關於" #: editor/editor_node.cpp msgid "Play the project." -msgstr "éŠçŽ©æ¤å°ˆæ¡ˆ" +msgstr "é‹è¡Œæ¤å°ˆæ¡ˆã€‚" #: editor/editor_node.cpp msgid "Play" -msgstr "é–‹å§‹" +msgstr "é‹è¡Œ" #: editor/editor_node.cpp msgid "Pause the scene" @@ -2377,58 +2377,58 @@ msgstr "åœæ¢" #: editor/editor_node.cpp msgid "Play the edited scene." -msgstr "" +msgstr "é‹è¡Œç·¨è¼¯éŽçš„å ´æ™¯ã€‚" #: editor/editor_node.cpp msgid "Play Scene" -msgstr "" +msgstr "é‹è¡Œå ´æ™¯" #: editor/editor_node.cpp msgid "Play custom scene" -msgstr "" +msgstr "é‹è¡Œè‡ªå®šç¾©å ´æ™¯" #: editor/editor_node.cpp msgid "Play Custom Scene" -msgstr "" +msgstr "é‹è¡Œè‡ªå®šç¾©å ´æ™¯" #: editor/editor_node.cpp msgid "Changing the video driver requires restarting the editor." -msgstr "" +msgstr "åœ¨æ›´å‹•é¡¯ç¤ºé©…å‹•å¾Œï¼Œå¿…é ˆé‡æ–°é–‹å•Ÿç·¨è¼¯å™¨ã€‚" #: editor/editor_node.cpp editor/project_settings_editor.cpp #: editor/settings_config_dialog.cpp -#, fuzzy msgid "Save & Restart" -msgstr "å¦å˜æ–°æª”" +msgstr "儲å˜ä¸¦é‡å•Ÿ" #: editor/editor_node.cpp -msgid "Spins when the editor window repaints!" -msgstr "" +#, fuzzy +msgid "Spins when the editor window redraws." +msgstr "åœ¨é‡æ–°ç¹ªè£½(repaint)編輯器視窗時,來個旋轉ï¼" #: editor/editor_node.cpp msgid "Update Always" -msgstr "" +msgstr "總是自動更新" #: editor/editor_node.cpp msgid "Update Changes" -msgstr "" +msgstr "有更動時自動更新" #: editor/editor_node.cpp msgid "Disable Update Spinner" -msgstr "" +msgstr "ç¦æ¢è‡ªå‹•æ›´æ–°" #: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp #: editor/project_manager.cpp msgid "Import" -msgstr "" +msgstr "å°Žå…¥" #: editor/editor_node.cpp msgid "FileSystem" -msgstr "" +msgstr "文件系統" #: editor/editor_node.cpp msgid "Inspector" -msgstr "" +msgstr "å±¬æ€§é¢æ¿" #: editor/editor_node.cpp #, fuzzy @@ -2437,96 +2437,95 @@ msgstr "節點" #: editor/editor_node.cpp msgid "Expand Bottom Panel" -msgstr "" +msgstr "å±•é–‹åº•éƒ¨é¢æ¿" #: editor/editor_node.cpp scene/resources/visual_shader.cpp msgid "Output" -msgstr "" +msgstr "輸出(output)" #: editor/editor_node.cpp msgid "Don't Save" -msgstr "" +msgstr "ä¸è¦å„²å˜" #: editor/editor_node.cpp msgid "Import Templates From ZIP File" -msgstr "" +msgstr "導入模æ¿ï¼ˆé€éŽZIP檔案)" #: editor/editor_node.cpp editor/project_export.cpp msgid "Export Project" -msgstr "" +msgstr "輸出專案" #: editor/editor_node.cpp msgid "Export Library" -msgstr "" +msgstr "輸出函å¼åº«" #: editor/editor_node.cpp msgid "Merge With Existing" -msgstr "" +msgstr "èˆ‡ç¾æœ‰å‡½å¼åº«åˆä½µ" #: editor/editor_node.cpp msgid "Password:" -msgstr "" +msgstr "密碼:" #: editor/editor_node.cpp msgid "Open & Run a Script" -msgstr "" +msgstr "開啟並é‹è¡Œè…³æœ¬" #: editor/editor_node.cpp msgid "New Inherited" -msgstr "" +msgstr "å¾žç¾æœ‰å ´æ™¯ä¸å»ºç«‹" #: editor/editor_node.cpp msgid "Load Errors" -msgstr "" +msgstr "è®€å–æ™‚出ç¾éŒ¯èª¤" #: editor/editor_node.cpp editor/plugins/tile_map_editor_plugin.cpp msgid "Select" -msgstr "" +msgstr "鏿“‡" #: editor/editor_node.cpp msgid "Open 2D Editor" -msgstr "" +msgstr "開啟2D編輯器" #: editor/editor_node.cpp msgid "Open 3D Editor" -msgstr "" +msgstr "開啟3D編輯器" #: editor/editor_node.cpp msgid "Open Script Editor" -msgstr "" +msgstr "開啟腳本編輯器" #: editor/editor_node.cpp editor/project_manager.cpp msgid "Open Asset Library" -msgstr "" +msgstr "é–‹å•Ÿç´ æå€‰åº«" #: editor/editor_node.cpp -#, fuzzy msgid "Open the next Editor" -msgstr "離開編輯器嗎?" +msgstr "開啟下一個編輯器" #: editor/editor_node.cpp msgid "Open the previous Editor" -msgstr "" +msgstr "開啟上一個編輯器" #: editor/editor_plugin.cpp msgid "Creating Mesh Previews" -msgstr "" +msgstr "å‰µå»ºç¶²æ ¼é 覽" #: editor/editor_plugin.cpp msgid "Thumbnail..." -msgstr "" +msgstr "縮圖…" #: editor/editor_plugin_settings.cpp msgid "Edit Plugin" -msgstr "" +msgstr "編輯擴充功能" #: editor/editor_plugin_settings.cpp msgid "Installed Plugins:" -msgstr "" +msgstr "已安è£çš„æ“´å……功能:" #: editor/editor_plugin_settings.cpp editor/plugin_config_dialog.cpp msgid "Update" -msgstr "" +msgstr "æ›´æ–°" #: editor/editor_plugin_settings.cpp editor/plugin_config_dialog.cpp #: editor/plugins/asset_library_editor_plugin.cpp @@ -3491,24 +3490,6 @@ msgid "Create Polygon" msgstr "新增資料夾" #: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Edit Polygon" -msgstr "新增資料夾" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Insert Point" -msgstr "" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -msgid "Edit Polygon (Remove Point)" -msgstr "" - -#: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy -msgid "Remove Polygon And Point" -msgstr "移除" - -#: editor/plugins/abstract_polygon_2d_editor.cpp #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #, fuzzy @@ -3528,6 +3509,24 @@ msgstr "" msgid "Erase points." msgstr "æ‰€æœ‰çš„é¸æ“‡" +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Edit Polygon" +msgstr "新增資料夾" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Insert Point" +msgstr "" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +msgid "Edit Polygon (Remove Point)" +msgstr "" + +#: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy +msgid "Remove Polygon And Point" +msgstr "移除" + #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp #: editor/plugins/animation_player_editor_plugin.cpp @@ -4333,6 +4332,16 @@ msgid "Move CanvasItem" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp +msgid "Presets for the anchors and margins values of a Control node." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp +msgid "" +"Children of containers have their anchors and margins values overridden by " +"their parent." +msgstr "" + +#: editor/plugins/canvas_item_editor_plugin.cpp msgid "Anchors only" msgstr "" @@ -5245,6 +5254,12 @@ msgid "Create UV Map" msgstr "" #: editor/plugins/polygon_2d_editor_plugin.cpp +msgid "" +"Polygon 2D has internal vertices, so it can no longer be edited in the " +"viewport." +msgstr "" + +#: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Create Polygon & UV" msgstr "" @@ -6373,7 +6388,7 @@ msgid "Post" msgstr "" #: editor/plugins/spatial_editor_plugin.cpp -msgid "Name-less gizmo" +msgid "Nameless gizmo" msgstr "" #: editor/plugins/sprite_editor_plugin.cpp @@ -6453,8 +6468,14 @@ msgid "(empty)" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animations" -msgstr "" +#, fuzzy +msgid "Animations:" +msgstr "動畫空間。" + +#: editor/plugins/sprite_frames_editor_plugin.cpp +#, fuzzy +msgid "New Animation" +msgstr "動畫最佳化" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed (FPS):" @@ -6465,8 +6486,9 @@ msgid "Loop" msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp -msgid "Animation Frames" -msgstr "" +#, fuzzy +msgid "Animation Frames:" +msgstr "動畫空間。" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Insert Empty (Before)" @@ -7288,6 +7310,19 @@ msgstr "" #: editor/project_manager.cpp msgid "" +"The following project settings file does not specify the version of Godot " +"through which it was created.\n" +"\n" +"%s\n" +"\n" +"If you proceed with opening it, it will be converted to Godot's current " +"configuration file format.\n" +"Warning: You will not be able to open the project with previous versions of " +"the engine anymore." +msgstr "" + +#: editor/project_manager.cpp +msgid "" "The following project settings file was generated by an older engine " "version, and needs to be converted for this version:\n" "\n" @@ -8827,10 +8862,6 @@ msgid "Build Project" msgstr "專案è¨å®š" #: modules/mono/editor/mono_bottom_panel.cpp -msgid "Warnings" -msgstr "" - -#: modules/mono/editor/mono_bottom_panel.cpp #, fuzzy msgid "View log" msgstr "éŽæ¿¾æª”案..." @@ -9483,6 +9514,13 @@ msgid "" "ParallaxLayer node only works when set as child of a ParallaxBackground node." msgstr "" +#: scene/2d/particles_2d.cpp +msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles2D node instead. You can use the \"Convert to " +"CPUParticles\" option for this purpose." +msgstr "" + #: scene/2d/particles_2d.cpp scene/3d/particles.cpp msgid "" "A material to process the particles is not assigned, so no behavior is " @@ -9638,6 +9676,13 @@ msgstr "" #: scene/3d/particles.cpp msgid "" +"GPU-based particles are not supported by the GLES2 video driver.\n" +"Use the CPUParticles node instead. You can use the \"Convert to CPUParticles" +"\" option for this purpose." +msgstr "" + +#: scene/3d/particles.cpp +msgid "" "Nothing is visible because meshes have not been assigned to draw passes." msgstr "" @@ -9668,21 +9713,6 @@ msgstr "" msgid "Path property must point to a valid Spatial node to work." msgstr "" -#: scene/3d/scenario_fx.cpp -msgid "WorldEnvironment needs an Environment resource." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." -msgstr "" - -#: scene/3d/scenario_fx.cpp -msgid "" -"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " -"this environment's Background Mode to Canvas (for 2D scenes)." -msgstr "" - #: scene/3d/soft_body.cpp msgid "This body will be ignored until you set a mesh" msgstr "" @@ -9706,6 +9736,21 @@ msgid "" "it as a child of a VehicleBody." msgstr "" +#: scene/3d/world_environment.cpp +msgid "WorldEnvironment needs an Environment resource." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." +msgstr "" + +#: scene/3d/world_environment.cpp +msgid "" +"This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " +"this environment's Background Mode to Canvas (for 2D scenes)." +msgstr "" + #: scene/animation/animation_blend_tree.cpp msgid "On BlendTree node '%s', animation not found: '%s'" msgstr "" @@ -9751,11 +9796,20 @@ msgid "This node has been deprecated. Use AnimationTree instead." msgstr "" #: scene/gui/color_picker.cpp +msgid "Pick a color from the screen." +msgstr "" + +#: scene/gui/color_picker.cpp msgid "Raw Mode" msgstr "" #: scene/gui/color_picker.cpp -msgid "Add current color as a preset" +msgid "Switch between hexadecimal and code values." +msgstr "" + +#: scene/gui/color_picker.cpp +#, fuzzy +msgid "Add current color as a preset." msgstr "將目å‰é¡è‰²è¨ç‚ºé è¨" #: scene/gui/dialogs.cpp @@ -9841,6 +9895,12 @@ msgstr "" msgid "Varyings can only be assigned in vertex function." msgstr "" +#~ msgid "Line:" +#~ msgstr "行:" + +#~ msgid "Col:" +#~ msgstr "列:" + #, fuzzy #~ msgid "Split already exists." #~ msgstr "Autoload「%sã€å·²ç¶“å˜åœ¨!" diff --git a/main/main.cpp b/main/main.cpp index f9044b61cd..ee13a4bacc 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -53,11 +53,11 @@ #include "drivers/register_driver_types.h" #include "main/app_icon.gen.h" #include "main/input_default.h" +#include "main/main_timer_sync.h" #include "main/performance.h" #include "main/splash.gen.h" #include "main/splash_editor.gen.h" #include "main/tests/test_main.h" -#include "main/timer_sync.h" #include "modules/register_module_types.h" #include "platform/register_platform_apis.h" #include "scene/main/scene_tree.h" @@ -394,7 +394,9 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph Vector<String> breakpoints; bool use_custom_res = true; bool force_res = false; +#ifdef TOOLS_ENABLED bool found_project = false; +#endif packed_data = PackedData::get_singleton(); if (!packed_data) @@ -746,7 +748,9 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph } if (globals->setup(project_path, main_pack, upwards) == OK) { +#ifdef TOOLS_ENABLED found_project = true; +#endif } else { #ifdef TOOLS_ENABLED @@ -922,13 +926,12 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph OS::get_singleton()->_allow_hidpi = GLOBAL_DEF("display/window/dpi/allow_hidpi", false); } - OS::get_singleton()->_allow_layered = GLOBAL_DEF("display/window/allow_per_pixel_transparency", false); - video_mode.use_vsync = GLOBAL_DEF("display/window/vsync/use_vsync", true); OS::get_singleton()->_use_vsync = video_mode.use_vsync; - video_mode.layered = GLOBAL_DEF("display/window/per_pixel_transparency", false); - video_mode.layered_splash = GLOBAL_DEF("display/window/per_pixel_transparency_splash", false); + OS::get_singleton()->_allow_layered = GLOBAL_DEF("display/window/per_pixel_transparency/allowed", false); + video_mode.layered = GLOBAL_DEF("display/window/per_pixel_transparency/enabled", false); + video_mode.layered_splash = GLOBAL_DEF("display/window/per_pixel_transparency/splash", false); GLOBAL_DEF("rendering/quality/intended_usage/framebuffer_allocation", 2); GLOBAL_DEF("rendering/quality/intended_usage/framebuffer_allocation.mobile", 3); @@ -1144,8 +1147,8 @@ Error Main::setup2(Thread::ID p_main_tid_override) { if (boot_logo_path != String()) { boot_logo.instance(); - Error err = ImageLoader::load_image(boot_logo_path, boot_logo); - if (err) + Error load_err = ImageLoader::load_image(boot_logo_path, boot_logo); + if (load_err) ERR_PRINTS("Non-existing or invalid boot splash at: " + boot_logo_path + ". Loading default splash."); } @@ -1273,7 +1276,9 @@ bool Main::start() { bool hasicon = false; String doc_tool; List<String> removal_docs; +#ifdef TOOLS_ENABLED bool doc_base = true; +#endif String game_path; String script; String test; @@ -1286,9 +1291,11 @@ bool Main::start() { List<String> args = OS::get_singleton()->get_cmdline_args(); for (int i = 0; i < args.size(); i++) { //parameters that do not have an argument to the right - if (args[i] == "--no-docbase") { - doc_base = false; + if (args[i] == "--check-only") { + check_only = true; #ifdef TOOLS_ENABLED + } else if (args[i] == "--no-docbase") { + doc_base = false; } else if (args[i] == "-e" || args[i] == "--editor") { editor = true; } else if (args[i] == "-p" || args[i] == "--project-manager") { @@ -1296,8 +1303,6 @@ bool Main::start() { #endif } else if (args[i].length() && args[i][0] != '-' && game_path == "") { game_path = args[i]; - } else if (args[i] == "--check-only") { - check_only = true; } //parameters that have an argument to the right else if (i < (args.size() - 1)) { @@ -1543,8 +1548,8 @@ bool Main::start() { Ref<PackedScene> ps = res; n = ps->instance(); } else if (res->is_class("Script")) { - Ref<Script> s = res; - StringName ibt = s->get_instance_base_type(); + Ref<Script> script_res = res; + StringName ibt = script_res->get_instance_base_type(); bool valid_type = ClassDB::is_parent_class(ibt, "Node"); ERR_EXPLAIN("Script does not inherit a Node: " + path); ERR_CONTINUE(!valid_type); @@ -1555,7 +1560,7 @@ bool Main::start() { ERR_CONTINUE(obj == NULL); n = Object::cast_to<Node>(obj); - n->set_script(s.get_ref_ptr()); + n->set_script(script_res.get_ref_ptr()); } ERR_EXPLAIN("Path in autoload not a node or script: " + path); diff --git a/main/timer_sync.cpp b/main/main_timer_sync.cpp index 5ee834880f..f7388c8517 100644 --- a/main/timer_sync.cpp +++ b/main/main_timer_sync.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* timer_sync.cpp */ +/* main_timer_sync.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,7 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "timer_sync.h" +#include "main_timer_sync.h" void MainFrameTime::clamp_idle(float min_idle_step, float max_idle_step) { if (idle_step < min_idle_step) { diff --git a/main/timer_sync.h b/main/main_timer_sync.h index fcce6d7a9a..179119edce 100644 --- a/main/timer_sync.h +++ b/main/main_timer_sync.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* timer_sync.h */ +/* main_timer_sync.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef TIMER_SYNC_H -#define TIMER_SYNC_H +#ifndef MAIN_TIMER_SYNC_H +#define MAIN_TIMER_SYNC_H #include "core/engine.h" @@ -98,4 +98,4 @@ public: MainFrameTime advance(float p_frame_slice, int p_iterations_per_second); }; -#endif // TIMER_SYNC_H +#endif // MAIN_TIMER_SYNC_H diff --git a/main/tests/test_gdscript.cpp b/main/tests/test_gdscript.cpp index 60f9568fbd..55e31a18c3 100644 --- a/main/tests/test_gdscript.cpp +++ b/main/tests/test_gdscript.cpp @@ -360,9 +360,6 @@ static void _parser_show_block(const GDScriptParser::BlockNode *p_block, int p_i case GDScriptParser::ControlFlowNode::CF_MATCH: { // FIXME: Implement } break; - case GDScriptParser::ControlFlowNode::CF_SWITCH: { - - } break; case GDScriptParser::ControlFlowNode::CF_CONTINUE: { _print_indent(p_indent, "continue"); @@ -911,11 +908,14 @@ MainLoop *test(TestType p_type) { List<String> cmdlargs = OS::get_singleton()->get_cmdline_args(); if (cmdlargs.empty()) { - //try editor! return NULL; } String test = cmdlargs.back()->get(); + if (!test.ends_with(".gd") && !test.ends_with(".gdc")) { + print_line("This test expects a path to a GDScript file as its last parameter. Got: " + test); + return NULL; + } FileAccess *fa = FileAccess::open(test, FileAccess::READ); @@ -1041,10 +1041,10 @@ MainLoop *test(TestType p_type) { } else if (p_type == TEST_BYTECODE) { - Vector<uint8_t> buf = GDScriptTokenizerBuffer::parse_code_string(code); + Vector<uint8_t> buf2 = GDScriptTokenizerBuffer::parse_code_string(code); String dst = test.get_basename() + ".gdc"; FileAccess *fw = FileAccess::open(dst, FileAccess::WRITE); - fw->store_buffer(buf.ptr(), buf.size()); + fw->store_buffer(buf2.ptr(), buf2.size()); memdelete(fw); } diff --git a/main/tests/test_image.cpp b/main/tests/test_image.cpp deleted file mode 100644 index ee4f43bae0..0000000000 --- a/main/tests/test_image.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/*************************************************************************/ -/* test_image.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "test_image.h" - -#include "core/io/image_loader.h" -#include "core/math/math_funcs.h" -#include "core/os/main_loop.h" -#include "core/print_string.h" - -namespace TestImage { - -class TestMainLoop : public MainLoop { - - bool quit; - -public: - virtual void input_event(const Ref<InputEvent> &p_event) { - } - - virtual void init() { - - quit = false; - } - virtual bool iteration(float p_time) { - - return quit; - } - - virtual bool idle(float p_time) { - return quit; - } - - virtual void finish() { - } -}; - -MainLoop *test() { - - return memnew(TestMainLoop); -} -} // namespace TestImage diff --git a/main/tests/test_image.h b/main/tests/test_image.h deleted file mode 100644 index b9b3c0cb48..0000000000 --- a/main/tests/test_image.h +++ /dev/null @@ -1,45 +0,0 @@ -/*************************************************************************/ -/* test_image.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef TEST_IMAGE_H -#define TEST_IMAGE_H - -/** - @author Juan Linietsky <reduzio@gmail.com> -*/ - -#include "core/os/main_loop.h" - -namespace TestImage { - -MainLoop *test(); -} - -#endif diff --git a/main/tests/test_main.cpp b/main/tests/test_main.cpp index 49f5cc5a18..22f1d7319f 100644 --- a/main/tests/test_main.cpp +++ b/main/tests/test_main.cpp @@ -36,7 +36,6 @@ #include "test_astar.h" #include "test_gdscript.h" #include "test_gui.h" -#include "test_image.h" #include "test_math.h" #include "test_oa_hash_map.h" #include "test_ordered_hash_map.h" @@ -61,7 +60,6 @@ const char **tests_get_names() { "gd_parser", "gd_compiler", "gd_bytecode", - "image", "ordered_hash_map", "astar", NULL @@ -134,11 +132,6 @@ MainLoop *test_main(String p_test, const List<String> &p_args) { return TestGDScript::test(TestGDScript::TEST_BYTECODE); } - if (p_test == "image") { - - return TestImage::test(); - } - if (p_test == "ordered_hash_map") { return TestOrderedHashMap::test(); @@ -149,6 +142,7 @@ MainLoop *test_main(String p_test, const List<String> &p_args) { return TestAStar::test(); } + print_line("Unknown test: " + p_test); return NULL; } diff --git a/main/tests/test_math.cpp b/main/tests/test_math.cpp index a082abcaba..f341159079 100644 --- a/main/tests/test_math.cpp +++ b/main/tests/test_math.cpp @@ -30,9 +30,9 @@ #include "test_math.h" +#include "core/math/basis.h" #include "core/math/camera_matrix.h" #include "core/math/math_funcs.h" -#include "core/math/matrix3.h" #include "core/math/transform.h" #include "core/os/file_access.h" #include "core/os/keyboard.h" diff --git a/main/tests/test_shader_lang.cpp b/main/tests/test_shader_lang.cpp index ebaf7fd602..dcb19b7df7 100644 --- a/main/tests/test_shader_lang.cpp +++ b/main/tests/test_shader_lang.cpp @@ -110,7 +110,7 @@ static String dump_node_code(SL::Node *p_node, int p_level) { for (Map<StringName, SL::ShaderNode::Uniform>::Element *E = pnode->uniforms.front(); E; E = E->next()) { String ucode = "uniform "; - ucode += _prestr(E->get().precission); + ucode += _prestr(E->get().precision); ucode += _typestr(E->get().type); ucode += " " + String(E->key()); @@ -137,7 +137,7 @@ static String dump_node_code(SL::Node *p_node, int p_level) { for (Map<StringName, SL::ShaderNode::Varying>::Element *E = pnode->varyings.front(); E; E = E->next()) { String vcode = "varying "; - vcode += _prestr(E->get().precission); + vcode += _prestr(E->get().precision); vcode += _typestr(E->get().type); vcode += " " + String(E->key()); @@ -149,11 +149,11 @@ static String dump_node_code(SL::Node *p_node, int p_level) { String header; header = _typestr(fnode->return_type) + " " + fnode->name + "("; - for (int i = 0; i < fnode->arguments.size(); i++) { + for (int j = 0; j < fnode->arguments.size(); j++) { - if (i > 0) + if (j > 0) header += ", "; - header += _prestr(fnode->arguments[i].precision) + _typestr(fnode->arguments[i].type) + " " + fnode->arguments[i].name; + header += _prestr(fnode->arguments[j].precision) + _typestr(fnode->arguments[j].type) + " " + fnode->arguments[j].name; } header += ")\n"; @@ -336,9 +336,9 @@ MainLoop *test() { print_line("Error at line: " + rtos(sl.get_error_line()) + ": " + sl.get_error_text()); return NULL; } else { - String code; - recreate_code(&code, sl.get_shader()); - print_line("code:\n\n" + code); + String code2; + recreate_code(&code2, sl.get_shader()); + print_line("code:\n\n" + code2); } return NULL; diff --git a/main/tests/test_string.cpp b/main/tests/test_string.cpp index 511646db0a..edc4fb0c97 100644 --- a/main/tests/test_string.cpp +++ b/main/tests/test_string.cpp @@ -1046,6 +1046,13 @@ bool test_32() { #undef STRIP_TEST } +bool test_33() { + OS::get_singleton()->print("\n\nTest 33: parse_utf8(null, -1)\n"); + + String empty; + return empty.parse_utf8(NULL, -1) == true; +} + typedef bool (*TestFunc)(void); TestFunc test_funcs[] = { @@ -1082,6 +1089,7 @@ TestFunc test_funcs[] = { test_30, test_31, test_32, + test_33, 0 }; diff --git a/methods.py b/methods.py index f8fc6c64ef..d8e90a8da5 100644 --- a/methods.py +++ b/methods.py @@ -61,14 +61,22 @@ def update_version(module_version_string=""): # NOTE: It is safe to generate this file here, since this is still executed serially fhash = open("core/version_hash.gen.h", "w") githash = "" - if os.path.isfile(".git/HEAD"): - head = open(".git/HEAD", "r").readline().strip() + gitfolder = ".git" + + if os.path.isfile(".git"): + module_folder = open(".git", "r").readline().strip() + if module_folder.startswith("gitdir: "): + gitfolder = module_folder[8:] + + if os.path.isfile(os.path.join(gitfolder, "HEAD")): + head = open(os.path.join(gitfolder, "HEAD"), "r").readline().strip() if head.startswith("ref: "): - head = ".git/" + head[5:] + head = os.path.join(gitfolder, head[5:]) if os.path.isfile(head): githash = open(head, "r").readline().strip() else: githash = head + fhash.write("#define VERSION_HASH \"" + githash + "\"") fhash.close() @@ -652,3 +660,10 @@ def detect_darwin_sdk_path(platform, env): print("Failed to find SDK path while running xcrun --sdk {} --show-sdk-path.".format(sdk_name)) raise +def get_compiler_version(env): + version = decode_utf8(subprocess.check_output([env['CXX'], '--version']).strip()) + match = re.search('[0-9][0-9.]*', version) + if match is not None: + return match.group().split('.') + else: + return None diff --git a/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj b/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj index a9a40c0508..569033d93c 100644 --- a/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj +++ b/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj @@ -17,6 +17,7 @@ 1FE9269F1FBBF86B00F53A6F /* CoreMedia.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FE926901FBBF78E00F53A6F /* CoreMedia.framework */; }; 1FE926A01FBBF86D00F53A6F /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FE9268E1FBBF77300F53A6F /* AudioToolbox.framework */; }; 1FE926A11FBBF86D00F53A6F /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FE9268F1FBBF77F00F53A6F /* CoreAudio.framework */; }; + E360193721F32F38009258C1 /* CoreVideo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E360193621F32F37009258C1 /* CoreVideo.framework */; }; DEADBEEF2F582BE20003B888 /* $binary.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DEADBEEF1F582BE20003B888 /* $binary.a */; }; 1FF8DBB11FBA9DE1009DE660 /* dummy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1FF8DBB01FBA9DE1009DE660 /* dummy.cpp */; }; 1FF4C1851F584E3F00A41E41 /* GameKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FF4C1841F584E3F00A41E41 /* GameKit.framework */; }; @@ -53,6 +54,7 @@ D0BCFE3418AEBDA2004A7AAE /* $binary.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = $binary.app; sourceTree = BUILT_PRODUCTS_DIR; }; D0BCFE3718AEBDA2004A7AAE /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; D0BCFE3918AEBDA2004A7AAE /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; + E360193621F32F37009258C1 /* CoreVideo.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreVideo.framework; path = System/Library/Frameworks/CoreVideo.framework; sourceTree = SDKROOT; }; D0BCFE3B18AEBDA2004A7AAE /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; D0BCFE3D18AEBDA2004A7AAE /* GLKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GLKit.framework; path = System/Library/Frameworks/GLKit.framework; sourceTree = SDKROOT; }; D0BCFE3F18AEBDA2004A7AAE /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = System/Library/Frameworks/OpenGLES.framework; sourceTree = SDKROOT; }; @@ -69,6 +71,7 @@ buildActionMask = 2147483647; files = ( D0BCFE3A18AEBDA2004A7AAE /* CoreGraphics.framework in Frameworks */, + E360193721F32F38009258C1 /* CoreVideo.framework in Frameworks */, 1FE926991FBBF85400F53A6F /* SystemConfiguration.framework in Frameworks */, 1FE9269A1FBBF85F00F53A6F /* Security.framework in Frameworks */, 1FE9269B1FBBF86200F53A6F /* QuartzCore.framework in Frameworks */, @@ -124,6 +127,7 @@ 1FE926911FBBF79500F53A6F /* CoreMotion.framework */, 1FE926901FBBF78E00F53A6F /* CoreMedia.framework */, 1FE9268F1FBBF77F00F53A6F /* CoreAudio.framework */, + E360193621F32F37009258C1 /* CoreVideo.framework */, 1FE9268E1FBBF77300F53A6F /* AudioToolbox.framework */, 1FF4C1861F584E5600A41E41 /* StoreKit.framework */, 1FF4C1841F584E3F00A41E41 /* GameKit.framework */, @@ -190,15 +194,82 @@ TargetAttributes = { D0BCFE3318AEBDA2004A7AAE = { DevelopmentTeam = $team_id; + ProvisioningStyle = Automatic; SystemCapabilities = { - com.apple.GameCenter = { - enabled = 1; + com.apple.AccessWiFi = { + enabled = $access_wifi; + }; + com.apple.ApplePay = { + enabled = 0; + }; + com.apple.ApplicationGroups.iOS = { + enabled = 0; + }; + com.apple.AutoFillCredentialProvider = { + enabled = 0; + }; + com.apple.BackgroundModes = { + enabled = 0; + }; + com.apple.ClassKit = { + enabled = 0; + }; + com.apple.DataProtection = { + enabled = 0; + }; + com.apple.GameCenter.iOS = { + enabled = $game_center; + }; + com.apple.HealthKit = { + enabled = 0; + }; + com.apple.HomeKit = { + enabled = 0; + }; + com.apple.HotspotConfiguration = { + enabled = 0; }; com.apple.InAppPurchase = { - enabled = 1; + enabled = $in_app_purchases; + }; + com.apple.InterAppAudio = { + enabled = 0; + }; + com.apple.Keychain = { + enabled = 0; + }; + com.apple.Maps.iOS = { + enabled = 0; + }; + com.apple.Multipath = { + enabled = 0; + }; + com.apple.NearFieldCommunicationTagReading = { + enabled = 0; + }; + com.apple.NetworkExtensions.iOS = { + enabled = 0; }; com.apple.Push = { - enabled = 1; + enabled = $push_notifications; + }; + com.apple.SafariKeychain = { + enabled = 0; + }; + com.apple.Siri = { + enabled = 0; + }; + com.apple.VPNLite = { + enabled = 0; + }; + com.apple.WAC = { + enabled = 0; + }; + com.apple.Wallet = { + enabled = 0; + }; + com.apple.iCloud = { + enabled = 0; }; }; }; @@ -277,6 +348,7 @@ CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "$code_sign_identity_debug"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "$code_sign_identity_debug"; COPY_PHASE_STRIP = NO; ENABLE_BITCODE = NO; @@ -400,7 +472,7 @@ D0BCFE7018AEBDA3004A7AAE /* Release */, ); defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; + defaultConfigurationName = Debug; }; D0BCFE7118AEBDA3004A7AAE /* Build configuration list for PBXNativeTarget "$binary" */ = { isa = XCConfigurationList; @@ -409,7 +481,7 @@ D0BCFE7318AEBDA3004A7AAE /* Release */, ); defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; + defaultConfigurationName = Debug; }; /* End XCConfigurationList section */ }; diff --git a/misc/dist/ios_xcode/godot_ios/godot_ios-Info.plist b/misc/dist/ios_xcode/godot_ios/godot_ios-Info.plist index 6907ae4a9d..1c68c72385 100644 --- a/misc/dist/ios_xcode/godot_ios/godot_ios-Info.plist +++ b/misc/dist/ios_xcode/godot_ios/godot_ios-Info.plist @@ -13,7 +13,7 @@ <key>CFBundleIcons~ipad</key> <dict/> <key>CFBundleIdentifier</key> - <string>$identifier</string> + <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> <key>CFBundleInfoDictionaryVersion</key> <string>6.0</string> <key>CFBundleName</key> @@ -30,26 +30,25 @@ <true/> <key>UIRequiredDeviceCapabilities</key> <array> - <string>armv7</string> - <string>gamekit</string> + $required_device_capabilities </array> + <key>NSCameraUsageDescription</key> + <string>$camera_usage_description</string> + <key>NSMicrophoneUsageDescription</key> + <string>$microphone_usage_description</string> + <key>NSPhotoLibraryUsageDescription</key> + <string>$photolibrary_usage_description</string> <key>UIRequiresFullScreen</key> <true/> <key>UIStatusBarHidden</key> <true/> <key>UISupportedInterfaceOrientations</key> <array> - <string>UIInterfaceOrientationLandscapeLeft</string> - <string>UIInterfaceOrientationLandscapeRight</string> - <string>UIInterfaceOrientationPortrait</string> - <string>UIInterfaceOrientationPortraitUpsideDown</string> + $interface_orientations </array> <key>UISupportedInterfaceOrientations~ipad</key> <array> - <string>UIInterfaceOrientationLandscapeLeft</string> - <string>UIInterfaceOrientationLandscapeRight</string> - <string>UIInterfaceOrientationPortrait</string> - <string>UIInterfaceOrientationPortraitUpsideDown</string> + $interface_orientations </array> $additional_plist_content </dict> diff --git a/misc/dist/linux/godot.6 b/misc/dist/linux/godot.6 index e6fd1b9991..078f8bcf91 100644 --- a/misc/dist/linux/godot.6 +++ b/misc/dist/linux/godot.6 @@ -56,7 +56,7 @@ Remote filesystem (<host/IP>[:<port>] address). Password for remote filesystem. .TP \fB\-\-audio\-driver\fR <driver> -Audio driver ('PulseAudio', 'ALSA'). +Audio driver ('PulseAudio', 'ALSA', 'Dummy'). .TP \fB\-\-video\-driver\fR <driver> Video driver ('GLES3', 'GLES2'). @@ -133,7 +133,7 @@ Only parse for errors and quit (use with --script). \fB\-\-export\fR <target> Export the project using the given export target. Export only main pack if path ends with .pck or .zip. .TP -\fB\-\-export\-debug\fR +\fB\-\-export\-debug\fR <target> Like \-\-export, but use debug template. .TP \fB\-\-doctool\fR <path> @@ -149,7 +149,7 @@ Build the scripting solutions (e.g. for C# projects). Generate JSON dump of the Godot API for GDNative bindings. .TP \fB\-\-test\fR <test> -Run a unit test ('string', 'math', 'physics', 'physics_2d', 'render', 'oa_hash_map', 'gui', 'shaderlang', 'gd_tokenizer', 'gd_parser', 'gd_compiler', 'gd_bytecode', 'image', 'ordered_hash_map'). +Run a unit test ('string', 'math', 'physics', 'physics_2d', 'render', 'oa_hash_map', 'gui', 'shaderlang', 'gd_tokenizer', 'gd_parser', 'gd_compiler', 'gd_bytecode', 'ordered_hash_map', 'astar'). .SH FILES XDG_DATA_CONFIG/godot/ or ~/.config/godot/ .RS diff --git a/misc/dist/osx_tools.app/Contents/Info.plist b/misc/dist/osx_tools.app/Contents/Info.plist index 97d769c824..2d6fa4d059 100755 --- a/misc/dist/osx_tools.app/Contents/Info.plist +++ b/misc/dist/osx_tools.app/Contents/Info.plist @@ -19,11 +19,11 @@ <key>CFBundlePackageType</key> <string>APPL</string> <key>CFBundleShortVersionString</key> - <string>3.0</string> + <string>3.1</string> <key>CFBundleSignature</key> <string>godot</string> <key>CFBundleVersion</key> - <string>3.0</string> + <string>3.1</string> <key>NSHumanReadableCopyright</key> <string>© 2007-2019 Juan Linietsky, Ariel Manzur & Godot Engine contributors</string> <key>LSMinimumSystemVersion</key> diff --git a/modules/bullet/SCsub b/modules/bullet/SCsub index 0416dd7f5f..7e714ba43f 100644 --- a/modules/bullet/SCsub +++ b/modules/bullet/SCsub @@ -187,8 +187,8 @@ if env['builtin_bullet']: thirdparty_sources = [thirdparty_dir + file for file in bullet2_src] env_bullet.Append(CPPPATH=[thirdparty_dir]) - if env['target'] == "debug" or env['target'] == "release_debug": - env_bullet.Append(CCFLAGS=['-DBT_DEBUG']) + # if env['target'] == "debug" or env['target'] == "release_debug": + # env_bullet.Append(CCFLAGS=['-DBT_DEBUG']) env_thirdparty = env_bullet.Clone() env_thirdparty.disable_warnings() diff --git a/modules/bullet/btRayShape.cpp b/modules/bullet/btRayShape.cpp index 935d86daa6..b902d08eca 100644 --- a/modules/bullet/btRayShape.cpp +++ b/modules/bullet/btRayShape.cpp @@ -79,7 +79,7 @@ void btRayShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVecto void btRayShape::getAabb(const btTransform &t, btVector3 &aabbMin, btVector3 &aabbMax) const { #define MARGIN_BROADPHASE 0.1 btVector3 localAabbMin(0, 0, 0); - btVector3 localAabbMax(m_shapeAxis * m_length); + btVector3 localAabbMax(m_shapeAxis * (m_cacheScaledLength + m_collisionMargin)); btTransformAabb(localAabbMin, localAabbMax, MARGIN_BROADPHASE, t, aabbMin, aabbMax); } @@ -97,8 +97,8 @@ void btRayShape::getPreferredPenetrationDirection(int index, btVector3 &penetrat void btRayShape::reload_cache() { - m_cacheScaledLength = m_length * m_localScaling[2] + m_collisionMargin; + m_cacheScaledLength = m_length * m_localScaling[2]; m_cacheSupportPoint.setIdentity(); - m_cacheSupportPoint.setOrigin(m_shapeAxis * m_cacheScaledLength); + m_cacheSupportPoint.setOrigin(m_shapeAxis * (m_cacheScaledLength + m_collisionMargin)); } diff --git a/modules/bullet/bullet_types_converter.h b/modules/bullet/bullet_types_converter.h index 57c3300b3d..ba36331d07 100644 --- a/modules/bullet/bullet_types_converter.h +++ b/modules/bullet/bullet_types_converter.h @@ -31,7 +31,7 @@ #ifndef BULLET_TYPES_CONVERTER_H #define BULLET_TYPES_CONVERTER_H -#include "core/math/matrix3.h" +#include "core/math/basis.h" #include "core/math/transform.h" #include "core/math/vector3.h" #include "core/typedefs.h" diff --git a/modules/bullet/collision_object_bullet.cpp b/modules/bullet/collision_object_bullet.cpp index 91a5ed095a..ef5f21fc21 100644 --- a/modules/bullet/collision_object_bullet.cpp +++ b/modules/bullet/collision_object_bullet.cpp @@ -69,8 +69,12 @@ void CollisionObjectBullet::ShapeWrapper::claim_bt_shape(const btVector3 &body_s CollisionObjectBullet::CollisionObjectBullet(Type p_type) : RIDBullet(), type(p_type), + instance_id(0), + collisionLayer(0), + collisionMask(0), collisionsEnabled(true), m_isStatic(false), + ray_pickable(false), bt_collision_object(NULL), body_scale(1., 1., 1.), force_shape_reset(false), diff --git a/modules/bullet/godot_ray_world_algorithm.cpp b/modules/bullet/godot_ray_world_algorithm.cpp index 449f625e17..3e06239453 100644 --- a/modules/bullet/godot_ray_world_algorithm.cpp +++ b/modules/bullet/godot_ray_world_algorithm.cpp @@ -35,8 +35,6 @@ #include <BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h> -#define RAY_STABILITY_MARGIN 0.1 - /** @author AndreaCatania */ @@ -102,7 +100,7 @@ void GodotRayWorldAlgorithm::processCollision(const btCollisionObjectWrapper *bo btScalar depth(ray_shape->getScaledLength() * (btResult.m_closestHitFraction - 1)); - if (depth >= -RAY_STABILITY_MARGIN) + if (depth >= -ray_shape->getMargin() * 0.5) depth = 0; if (ray_shape->getSlipsOnSlope()) diff --git a/modules/bullet/godot_result_callbacks.cpp b/modules/bullet/godot_result_callbacks.cpp index 7babfcc133..360950c4c7 100644 --- a/modules/bullet/godot_result_callbacks.cpp +++ b/modules/bullet/godot_result_callbacks.cpp @@ -333,14 +333,6 @@ void GodotDeepPenetrationContactResultCallback::addContactPoint(const btVector3 m_other_compound_shape_index = isSwapped ? m_index0 : m_index1; m_pointWorld = isSwapped ? (pointInWorldOnB + (normalOnBInWorld * depth)) : pointInWorldOnB; - const btCollisionObjectWrapper *bw0 = m_body0Wrap; - if (isSwapped) - bw0 = m_body1Wrap; - - if (bw0->getCollisionShape()->getShapeType() == CUSTOM_CONVEX_SHAPE_TYPE) { - m_pointNormalWorld = bw0->m_worldTransform.getBasis().transpose() * btVector3(0, 0, 1); - } else { - m_pointNormalWorld = isSwapped ? normalOnBInWorld * -1 : normalOnBInWorld; - } + m_pointNormalWorld = isSwapped ? normalOnBInWorld * -1 : normalOnBInWorld; } } diff --git a/modules/bullet/rigid_body_bullet.h b/modules/bullet/rigid_body_bullet.h index 784e99ab86..1e1bea846a 100644 --- a/modules/bullet/rigid_body_bullet.h +++ b/modules/bullet/rigid_body_bullet.h @@ -167,7 +167,7 @@ public: KinematicShape() : shape(NULL) {} - const bool is_active() const { return shape; } + bool is_active() const { return shape; } }; struct KinematicUtilities { diff --git a/modules/bullet/space_bullet.cpp b/modules/bullet/space_bullet.cpp index 6562b18b3c..8fb8eba057 100644 --- a/modules/bullet/space_bullet.cpp +++ b/modules/bullet/space_bullet.cpp @@ -658,6 +658,8 @@ void SpaceBullet::check_ghost_overlaps() { for (x = areas.size() - 1; 0 <= x; --x) { area = areas[x]; + btVector3 area_scale(area->get_bt_body_scale()); + if (!area->is_monitoring()) continue; @@ -681,9 +683,10 @@ void SpaceBullet::check_ghost_overlaps() { bool hasOverlap = false; btCollisionObject *overlapped_bt_co = ghostOverlaps[i]; RigidCollisionObjectBullet *otherObject = static_cast<RigidCollisionObjectBullet *>(overlapped_bt_co->getUserPointer()); + btVector3 other_body_scale(otherObject->get_bt_body_scale()); if (!area->is_transform_changed() && !otherObject->is_transform_changed()) { - hasOverlap = true; + hasOverlap = -1 != area->find_overlapping_object(otherObject); goto collision_found; } @@ -698,19 +701,38 @@ void SpaceBullet::check_ghost_overlaps() { if (!area->get_bt_shape(y)->isConvex()) continue; - gjk_input.m_transformA = area->get_transform__bullet() * area->get_bt_shape_transform(y); + btTransform area_shape_treansform(area->get_bt_shape_transform(y)); + area_shape_treansform.getOrigin() *= area_scale; + + gjk_input.m_transformA = + area->get_transform__bullet() * + area_shape_treansform; + area_shape = static_cast<btConvexShape *>(area->get_bt_shape(y)); // For each other object shape for (z = otherObject->get_shape_count() - 1; 0 <= z; --z) { other_body_shape = static_cast<btCollisionShape *>(otherObject->get_bt_shape(z)); - gjk_input.m_transformB = otherObject->get_transform__bullet() * otherObject->get_bt_shape_transform(z); + + if (other_body_shape->isConcave()) + continue; + + btTransform other_shape_transform(otherObject->get_bt_shape_transform(z)); + other_shape_transform.getOrigin() *= other_body_scale; + + gjk_input.m_transformB = + otherObject->get_transform__bullet() * + other_shape_transform; if (other_body_shape->isConvex()) { btPointCollector result; - btGjkPairDetector gjk_pair_detector(area_shape, static_cast<btConvexShape *>(other_body_shape), gjk_simplex_solver, gjk_epa_pen_solver); + btGjkPairDetector gjk_pair_detector( + area_shape, + static_cast<btConvexShape *>(other_body_shape), + gjk_simplex_solver, + gjk_epa_pen_solver); gjk_pair_detector.getClosestPoints(gjk_input, result, 0); if (0 >= result.m_distance) { @@ -1224,6 +1246,21 @@ bool SpaceBullet::RFP_convex_world_test(const btConvexShape *p_shapeA, const btC return false; } +void SpaceBullet::convert_to_separation_result(PhysicsServer::SeparationResult *r_result, const SpaceBullet::RecoverResult &p_recover_result, int p_shape_id, const btCollisionObject *p_other_object) const { + + const btRigidBody *btRigid = static_cast<const btRigidBody *>(p_other_object); + CollisionObjectBullet *collisionObject = static_cast<CollisionObjectBullet *>(p_other_object->getUserPointer()); + + r_result->collision_depth = p_recover_result.penetration_distance; + B_TO_G(p_recover_result.pointWorld, r_result->collision_point); + B_TO_G(p_recover_result.normal, r_result->collision_normal); + B_TO_G(btRigid->getVelocityInLocalPoint(p_recover_result.pointWorld - btRigid->getWorldTransform().getOrigin()), r_result->collider_velocity); + r_result->collision_local_shape = p_shape_id; + r_result->collider_id = collisionObject->get_instance_id(); + r_result->collider = collisionObject->get_self(); + r_result->collider_shape = p_recover_result.other_compound_shape_index; +} + int SpaceBullet::recover_from_penetration_ray(RigidBodyBullet *p_body, const btTransform &p_body_position, btScalar p_recover_movement_scale, bool p_infinite_inertia, int p_result_max, btVector3 &r_delta_recover_movement, PhysicsServer::SeparationResult *r_results) { RecoverPenetrationBroadPhaseCallback recover_broad_result(p_body->get_bt_collision_object(), p_body->get_collision_layer(), p_body->get_collision_mask()); @@ -1275,22 +1312,19 @@ int SpaceBullet::recover_from_penetration_ray(RigidBodyBullet *p_body, const btT btCompoundShape *cs = static_cast<btCompoundShape *>(otherObject->getCollisionShape()); for (int x = cs->getNumChildShapes() - 1; 0 <= x; --x) { - RecoverResult r_recover_result; - if (RFP_convex_world_test(kin_shape.shape, cs->getChildShape(x), p_body->get_bt_collision_object(), otherObject, kinIndex, x, body_shape_position, otherObject->getWorldTransform() * cs->getChildTransform(x), p_recover_movement_scale, r_delta_recover_movement, &r_recover_result)) { + RecoverResult recover_result; + if (RFP_convex_world_test(kin_shape.shape, cs->getChildShape(x), p_body->get_bt_collision_object(), otherObject, kinIndex, x, body_shape_position, otherObject->getWorldTransform() * cs->getChildTransform(x), p_recover_movement_scale, r_delta_recover_movement, &recover_result)) { - const btRigidBody *btRigid = static_cast<const btRigidBody *>(otherObject); - CollisionObjectBullet *collisionObject = static_cast<CollisionObjectBullet *>(otherObject->getUserPointer()); - - r_results[ray_index].collision_depth = r_recover_result.penetration_distance; - B_TO_G(r_recover_result.pointWorld, r_results[ray_index].collision_point); - B_TO_G(r_recover_result.normal, r_results[ray_index].collision_normal); - B_TO_G(btRigid->getVelocityInLocalPoint(r_recover_result.pointWorld - btRigid->getWorldTransform().getOrigin()), r_results[ray_index].collider_velocity); - r_results[ray_index].collision_local_shape = kinIndex; - r_results[ray_index].collider_id = collisionObject->get_instance_id(); - r_results[ray_index].collider = collisionObject->get_self(); - r_results[ray_index].collider_shape = r_recover_result.other_compound_shape_index; + convert_to_separation_result(&r_results[ray_index], recover_result, kinIndex, otherObject); } } + } else { + + RecoverResult recover_result; + if (RFP_convex_world_test(kin_shape.shape, otherObject->getCollisionShape(), p_body->get_bt_collision_object(), otherObject, kinIndex, 0, body_shape_position, otherObject->getWorldTransform(), p_recover_movement_scale, r_delta_recover_movement, &recover_result)) { + + convert_to_separation_result(&r_results[ray_index], recover_result, kinIndex, otherObject); + } } } diff --git a/modules/bullet/space_bullet.h b/modules/bullet/space_bullet.h index 9f36c63982..7bf6a216b5 100644 --- a/modules/bullet/space_bullet.h +++ b/modules/bullet/space_bullet.h @@ -212,6 +212,7 @@ private: /// Using this we leave Bullet to select the best algorithm, For example GJK in case we have Convex Convex, or a Bullet accelerated algorithm bool RFP_convex_world_test(const btConvexShape *p_shapeA, const btCollisionShape *p_shapeB, btCollisionObject *p_objectA, btCollisionObject *p_objectB, int p_shapeId_A, int p_shapeId_B, const btTransform &p_transformA, const btTransform &p_transformB, btScalar p_recover_movement_scale, btVector3 &r_delta_recover_movement, RecoverResult *r_recover_result = NULL); + void convert_to_separation_result(PhysicsServer::SeparationResult *r_result, const SpaceBullet::RecoverResult &p_recover_result, int p_shape_id, const btCollisionObject *p_other_object) const; int recover_from_penetration_ray(RigidBodyBullet *p_body, const btTransform &p_body_position, btScalar p_recover_movement_scale, bool p_infinite_inertia, int p_result_max, btVector3 &r_delta_recover_movement, PhysicsServer::SeparationResult *r_results); }; #endif diff --git a/modules/csg/csg.cpp b/modules/csg/csg.cpp index 12282b4730..fb7f829cf0 100644 --- a/modules/csg/csg.cpp +++ b/modules/csg/csg.cpp @@ -32,7 +32,7 @@ #include "core/math/face3.h" #include "core/math/geometry.h" #include "core/os/os.h" -#include "core/sort.h" +#include "core/sort_array.h" #include "thirdparty/misc/triangulator.h" void CSGBrush::clear() { @@ -666,14 +666,14 @@ void CSGBrushOperation::_add_poly_points(const BuildPoly &p_poly, int p_edge, in if (opposite_point == prev_point) continue; //not going back - EdgeSort e; + EdgeSort e2; Vector2 local_vec = t2d.xform(p_poly.points[opposite_point].point); - e.angle = -local_vec.angle(); //negate so we can sort by minimum angle - e.edge = edge; - e.edge_point = opposite_point; - e.prev_point = to_point; + e2.angle = -local_vec.angle(); //negate so we can sort by minimum angle + e2.edge = edge; + e2.edge_point = opposite_point; + e2.prev_point = to_point; - next_edges.push_back(e); + next_edges.push_back(e2); } //finally, sort by minimum angle diff --git a/modules/csg/csg.h b/modules/csg/csg.h index ac16575e82..4fa1a945cc 100644 --- a/modules/csg/csg.h +++ b/modules/csg/csg.h @@ -31,7 +31,6 @@ #ifndef CSG_H #define CSG_H -#include "core/dvector.h" #include "core/map.h" #include "core/math/aabb.h" #include "core/math/plane.h" @@ -39,6 +38,7 @@ #include "core/math/transform.h" #include "core/math/vector3.h" #include "core/oa_hash_map.h" +#include "core/pool_vector.h" #include "scene/resources/material.h" struct CSGBrush { diff --git a/modules/csg/csg_shape.cpp b/modules/csg/csg_shape.cpp index f62e6f5c40..f274fff3f3 100644 --- a/modules/csg/csg_shape.cpp +++ b/modules/csg/csg_shape.cpp @@ -531,6 +531,13 @@ void CSGShape::_notification(int p_what) { } } + if (p_what == NOTIFICATION_VISIBILITY_CHANGED) { + + if (parent) { + parent->_make_dirty(); + } + } + if (p_what == NOTIFICATION_EXIT_TREE) { if (parent) diff --git a/modules/csg/doc_classes/CSGShape.xml b/modules/csg/doc_classes/CSGShape.xml index 56087cbb82..d304d0179f 100644 --- a/modules/csg/doc_classes/CSGShape.xml +++ b/modules/csg/doc_classes/CSGShape.xml @@ -29,6 +29,12 @@ Returns an individual bit on the collision mask. </description> </method> + <method name="get_meshes" qualifiers="const"> + <return type="Array"> + </return> + <description> + </description> + </method> <method name="is_root_shape" qualifiers="const"> <return type="bool"> </return> diff --git a/modules/dds/texture_loader_dds.cpp b/modules/dds/texture_loader_dds.cpp index a063942269..0a94690989 100644 --- a/modules/dds/texture_loader_dds.cpp +++ b/modules/dds/texture_loader_dds.cpp @@ -263,14 +263,14 @@ RES ResourceFormatDDS::load(const String &p_path, const String &p_original_path, colsize = 4; } - int w = width; - int h = height; + int w2 = width; + int h2 = height; for (uint32_t i = 1; i < mipmaps; i++) { - w = (w + 1) >> 1; - h = (h + 1) >> 1; - size += w * h * info.block_size; + w2 = (w2 + 1) >> 1; + h2 = (h2 + 1) >> 1; + size += w2 * h2 * info.block_size; } src_data.resize(size + 256 * colsize); diff --git a/modules/enet/doc_classes/NetworkedMultiplayerENet.xml b/modules/enet/doc_classes/NetworkedMultiplayerENet.xml index 4976a90945..c9a7d96ae7 100644 --- a/modules/enet/doc_classes/NetworkedMultiplayerENet.xml +++ b/modules/enet/doc_classes/NetworkedMultiplayerENet.xml @@ -36,7 +36,7 @@ <argument index="4" name="client_port" type="int" default="0"> </argument> <description> - Create client that connects to a server at [code]address[/code] using specified [code]port[/code]. The given address needs to be either a fully qualified domain nome (e.g. [code]www.example.com[/code]) or an IP address in IPv4 or IPv6 format (e.g. [code]192.168.1.1[/code]). The [code]port[/code] is the port the server is listening on. The [code]in_bandwidth[/code] and [code]out_bandwidth[/code] parameters can be used to limit the incoming and outgoing bandwidth to the given number of bytes per second. The default of 0 means unlimited bandwidth. Note that ENet will strategically drop packets on specific sides of a connection between peers to ensure the peer's bandwidth is not overwhelmed. The bandwidth parameters also determine the window size of a connection which limits the amount of reliable packets that may be in transit at any given time. Returns [code]OK[/code] if a client was created, [code]ERR_ALREADY_IN_USE[/code] if this NetworkedMultiplayerEnet instance already has an open connection (in which case you need to call [method close_connection] first) or [code]ERR_CANT_CREATE[/code] if the client could not be created. If [code]client_port[/code] is specified, the client will also listen to the given port, this is useful in some NAT traversal technique. + Create client that connects to a server at [code]address[/code] using specified [code]port[/code]. The given address needs to be either a fully qualified domain name (e.g. [code]www.example.com[/code]) or an IP address in IPv4 or IPv6 format (e.g. [code]192.168.1.1[/code]). The [code]port[/code] is the port the server is listening on. The [code]in_bandwidth[/code] and [code]out_bandwidth[/code] parameters can be used to limit the incoming and outgoing bandwidth to the given number of bytes per second. The default of 0 means unlimited bandwidth. Note that ENet will strategically drop packets on specific sides of a connection between peers to ensure the peer's bandwidth is not overwhelmed. The bandwidth parameters also determine the window size of a connection which limits the amount of reliable packets that may be in transit at any given time. Returns [code]OK[/code] if a client was created, [code]ERR_ALREADY_IN_USE[/code] if this NetworkedMultiplayerEnet instance already has an open connection (in which case you need to call [method close_connection] first) or [code]ERR_CANT_CREATE[/code] if the client could not be created. If [code]client_port[/code] is specified, the client will also listen to the given port, this is useful in some NAT traversal technique. </description> </method> <method name="create_server"> diff --git a/modules/enet/networked_multiplayer_enet.cpp b/modules/enet/networked_multiplayer_enet.cpp index e53846e269..000917507a 100644 --- a/modules/enet/networked_multiplayer_enet.cpp +++ b/modules/enet/networked_multiplayer_enet.cpp @@ -231,6 +231,13 @@ void NetworkedMultiplayerENet::poll() { break; } + // A client joined with an invalid ID (neagtive values, 0, and 1 are reserved). + // Probably trying to exploit us. + if (server && ((int)event.data < 2 || peer_map.has((int)event.data))) { + enet_peer_reset(event.peer); + ERR_CONTINUE(true); + } + int *new_id = memnew(int); *new_id = event.data; @@ -426,7 +433,6 @@ bool NetworkedMultiplayerENet::is_server() const { void NetworkedMultiplayerENet::close_connection(uint32_t wait_usec) { ERR_FAIL_COND(!active); - ERR_FAIL_COND(wait_usec < 0); _pop_current_packet(); diff --git a/modules/gdnative/arvr/arvr_interface_gdnative.cpp b/modules/gdnative/arvr/arvr_interface_gdnative.cpp index 01fbc316cf..9cd37ac950 100644 --- a/modules/gdnative/arvr/arvr_interface_gdnative.cpp +++ b/modules/gdnative/arvr/arvr_interface_gdnative.cpp @@ -31,7 +31,7 @@ #include "arvr_interface_gdnative.h" #include "main/input_default.h" #include "servers/arvr/arvr_positional_tracker.h" -#include "servers/visual/visual_server_global.h" +#include "servers/visual/visual_server_globals.h" ARVRInterfaceGDNative::ARVRInterfaceGDNative() { // testing @@ -223,7 +223,7 @@ void GDAPI godot_arvr_register_interface(const godot_arvr_interface_gdnative *p_ Ref<ARVRInterfaceGDNative> new_interface; new_interface.instance(); - new_interface->set_interface((godot_arvr_interface_gdnative *const)p_interface); + new_interface->set_interface((const godot_arvr_interface_gdnative *)p_interface); ARVRServer::get_singleton()->add_interface(new_interface); } diff --git a/modules/gdnative/gdnative/array.cpp b/modules/gdnative/gdnative/array.cpp index 18da9d811e..6849ff03d7 100644 --- a/modules/gdnative/gdnative/array.cpp +++ b/modules/gdnative/gdnative/array.cpp @@ -34,7 +34,7 @@ #include "core/os/memory.h" #include "core/color.h" -#include "core/dvector.h" +#include "core/pool_vector.h" #include "core/variant.h" diff --git a/modules/gdnative/gdnative/basis.cpp b/modules/gdnative/gdnative/basis.cpp index 4441a03ca1..d77c7d91ac 100644 --- a/modules/gdnative/gdnative/basis.cpp +++ b/modules/gdnative/gdnative/basis.cpp @@ -30,7 +30,7 @@ #include "gdnative/basis.h" -#include "core/math/matrix3.h" +#include "core/math/basis.h" #include "core/variant.h" #ifdef __cplusplus diff --git a/modules/gdnative/gdnative/dictionary.cpp b/modules/gdnative/gdnative/dictionary.cpp index a18d221a7c..2c6c9e2de2 100644 --- a/modules/gdnative/gdnative/dictionary.cpp +++ b/modules/gdnative/gdnative/dictionary.cpp @@ -155,12 +155,26 @@ godot_string GDAPI godot_dictionary_to_json(const godot_dictionary *p_self) { return raw_dest; } +// GDNative core 1.1 + godot_bool GDAPI godot_dictionary_erase_with_return(godot_dictionary *p_self, const godot_variant *p_key) { Dictionary *self = (Dictionary *)p_self; const Variant *key = (const Variant *)p_key; return self->erase(*key); } +godot_variant GDAPI godot_dictionary_get_with_default(const godot_dictionary *p_self, const godot_variant *p_key, const godot_variant *p_default) { + const Dictionary *self = (const Dictionary *)p_self; + const Variant *key = (const Variant *)p_key; + const Variant *def = (const Variant *)p_default; + + godot_variant raw_dest; + Variant *dest = (Variant *)&raw_dest; + memnew_placement(dest, Variant(self->get(*key, *def))); + + return raw_dest; +} + #ifdef __cplusplus } #endif diff --git a/modules/gdnative/gdnative/pool_arrays.cpp b/modules/gdnative/gdnative/pool_arrays.cpp index 68e064d829..74c540ca14 100644 --- a/modules/gdnative/gdnative/pool_arrays.cpp +++ b/modules/gdnative/gdnative/pool_arrays.cpp @@ -31,7 +31,7 @@ #include "gdnative/pool_arrays.h" #include "core/array.h" -#include "core/dvector.h" +#include "core/pool_vector.h" #include "core/variant.h" #include "core/color.h" diff --git a/modules/gdnative/gdnative/string.cpp b/modules/gdnative/gdnative/string.cpp index 4b8d79305c..913c57eb56 100644 --- a/modules/gdnative/gdnative/string.cpp +++ b/modules/gdnative/gdnative/string.cpp @@ -30,7 +30,7 @@ #include "gdnative/string.h" -#include "core/string_db.h" +#include "core/string_name.h" #include "core/ustring.h" #include "core/variant.h" diff --git a/modules/gdnative/gdnative/string_name.cpp b/modules/gdnative/gdnative/string_name.cpp index d2862c5980..dcbb773c25 100644 --- a/modules/gdnative/gdnative/string_name.cpp +++ b/modules/gdnative/gdnative/string_name.cpp @@ -30,7 +30,7 @@ #include "gdnative/string_name.h" -#include "core/string_db.h" +#include "core/string_name.h" #include "core/ustring.h" #include <string.h> diff --git a/modules/gdnative/gdnative_api.json b/modules/gdnative/gdnative_api.json index 7680471409..bdcd51085f 100644 --- a/modules/gdnative/gdnative_api.json +++ b/modules/gdnative/gdnative_api.json @@ -107,6 +107,23 @@ ] }, { + "name": "godot_dictionary_get_with_default", + "return_type": "godot_variant", + "arguments": [ + ["const godot_dictionary *", "p_self"], + ["const godot_variant *", "p_key"], + ["const godot_variant *", "p_default"] + ] + }, + { + "name": "godot_dictionary_erase_with_return", + "return_type": "bool", + "arguments": [ + ["godot_dictionary *", "p_self"], + ["const godot_variant *", "p_key"] + ] + }, + { "name": "godot_node_path_get_as_property_path", "return_type": "godot_node_path", "arguments": [ @@ -234,14 +251,6 @@ ] }, { - "name": "godot_dictionary_erase_with_return", - "return_type": "bool", - "arguments": [ - ["godot_dictionary *", "p_self"], - ["const godot_variant *", "p_key"] - ] - }, - { "name": "godot_is_instance_valid", "return_type": "bool", "arguments": [ diff --git a/modules/gdnative/gdnative_builders.py b/modules/gdnative/gdnative_builders.py index cd356ce513..5fd5971fd1 100644 --- a/modules/gdnative/gdnative_builders.py +++ b/modules/gdnative/gdnative_builders.py @@ -213,7 +213,7 @@ def _build_gdnative_api_struct_source(api): 'extern const godot_gdnative_core_api_struct api_struct = {', '\tGDNATIVE_' + api['core']['type'] + ',', '\t{' + str(api['core']['version']['major']) + ', ' + str(api['core']['version']['minor']) + '},', - '\tNULL,', + '\t(const godot_gdnative_api_struct *)&api_1_1,', '\t' + str(len(api['extensions'])) + ',', '\tgdnative_extensions_pointers,', ] diff --git a/modules/gdnative/include/gdnative/dictionary.h b/modules/gdnative/include/gdnative/dictionary.h index 7703742899..14e35b4692 100644 --- a/modules/gdnative/include/gdnative/dictionary.h +++ b/modules/gdnative/include/gdnative/dictionary.h @@ -94,8 +94,12 @@ godot_bool GDAPI godot_dictionary_operator_equal(const godot_dictionary *p_self, godot_string GDAPI godot_dictionary_to_json(const godot_dictionary *p_self); +// GDNative core 1.1 + godot_bool GDAPI godot_dictionary_erase_with_return(godot_dictionary *p_self, const godot_variant *p_key); +godot_variant GDAPI godot_dictionary_get_with_default(const godot_dictionary *p_self, const godot_variant *p_key, const godot_variant *p_default); + #ifdef __cplusplus } #endif diff --git a/modules/gdnative/include/videodecoder/godot_videodecoder.h b/modules/gdnative/include/videodecoder/godot_videodecoder.h index 360fc0f5f5..1b08be30f0 100644 --- a/modules/gdnative/include/videodecoder/godot_videodecoder.h +++ b/modules/gdnative/include/videodecoder/godot_videodecoder.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/modules/gdnative/nativescript/nativescript.cpp b/modules/gdnative/nativescript/nativescript.cpp index 0370060937..9fd0a2e8ec 100644 --- a/modules/gdnative/nativescript/nativescript.cpp +++ b/modules/gdnative/nativescript/nativescript.cpp @@ -39,7 +39,7 @@ #include "core/project_settings.h" #include "scene/main/scene_tree.h" -#include "scene/resources/scene_format_text.h" +#include "scene/resources/resource_format_text.h" #include <stdlib.h> diff --git a/modules/gdnative/pluginscript/pluginscript_language.cpp b/modules/gdnative/pluginscript/pluginscript_language.cpp index ca1dd66a13..c9d92c09ed 100644 --- a/modules/gdnative/pluginscript/pluginscript_language.cpp +++ b/modules/gdnative/pluginscript/pluginscript_language.cpp @@ -173,8 +173,7 @@ Error PluginScriptLanguage::complete_code(const String &p_code, const String &p_ for (int i = 0; i < options.size(); i++) { r_options->push_back(String(options[i])); } - Error err = *(Error *)&tmp; - return err; + return (Error)tmp; } return ERR_UNAVAILABLE; } diff --git a/modules/gdnative/register_types.cpp b/modules/gdnative/register_types.cpp index b38de75caa..2094dca6e4 100644 --- a/modules/gdnative/register_types.cpp +++ b/modules/gdnative/register_types.cpp @@ -125,8 +125,8 @@ static void actual_discoverer_handler() { // Check for removed files if (!changed) { - for (int i = 0; i < current_files.size(); i++) { - if (!file_paths.has(current_files[i])) { + for (int j = 0; j < current_files.size(); j++) { + if (!file_paths.has(current_files[j])) { changed = true; break; } diff --git a/modules/gdnative/videodecoder/register_types.cpp b/modules/gdnative/videodecoder/register_types.cpp index ea78cb1970..0a0b2f64d5 100644 --- a/modules/gdnative/videodecoder/register_types.cpp +++ b/modules/gdnative/videodecoder/register_types.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/modules/gdnative/videodecoder/register_types.h b/modules/gdnative/videodecoder/register_types.h index dd1943fc47..f082343d8c 100644 --- a/modules/gdnative/videodecoder/register_types.h +++ b/modules/gdnative/videodecoder/register_types.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/modules/gdnative/videodecoder/video_stream_gdnative.cpp b/modules/gdnative/videodecoder/video_stream_gdnative.cpp index a1590cef43..8c2a84f60b 100644 --- a/modules/gdnative/videodecoder/video_stream_gdnative.cpp +++ b/modules/gdnative/videodecoder/video_stream_gdnative.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/modules/gdnative/videodecoder/video_stream_gdnative.h b/modules/gdnative/videodecoder/video_stream_gdnative.h index f9dec46b72..aafd02f33d 100644 --- a/modules/gdnative/videodecoder/video_stream_gdnative.h +++ b/modules/gdnative/videodecoder/video_stream_gdnative.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp index 6d85eb3c90..dd9b36fd8c 100644 --- a/modules/gdscript/gdscript.cpp +++ b/modules/gdscript/gdscript.cpp @@ -483,7 +483,7 @@ bool GDScript::_update_exports() { placeholder_fallback_enabled = true; return false; } - } else if (!valid || placeholder_fallback_enabled) { + } else if (placeholder_fallback_enabled) { return false; } @@ -1108,12 +1108,12 @@ void GDScriptInstance::get_property_list(List<PropertyInfo> *p_properties) const //instance a fake script for editing the values Vector<_GDScriptMemberSort> msort; - for (Map<StringName, PropertyInfo>::Element *E = sptr->member_info.front(); E; E = E->next()) { + for (Map<StringName, PropertyInfo>::Element *F = sptr->member_info.front(); F; F = F->next()) { _GDScriptMemberSort ms; - ERR_CONTINUE(!sptr->member_indices.has(E->key())); - ms.index = sptr->member_indices[E->key()].index; - ms.name = E->key(); + ERR_CONTINUE(!sptr->member_indices.has(F->key())); + ms.index = sptr->member_indices[F->key()].index; + ms.name = F->key(); msort.push_back(ms); } diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp index e59b57b39a..b2b7b1c260 100644 --- a/modules/gdscript/gdscript_compiler.cpp +++ b/modules/gdscript/gdscript_compiler.cpp @@ -1360,15 +1360,15 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Blo // jump unconditionally // continue address // compile the condition - int ret = _parse_expression(codegen, branch.compiled_pattern, p_stack_level); - if (ret < 0) { + int ret2 = _parse_expression(codegen, branch.compiled_pattern, p_stack_level); + if (ret2 < 0) { memdelete(id); memdelete(op); return ERR_PARSE_ERROR; } codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP_IF); - codegen.opcodes.push_back(ret); + codegen.opcodes.push_back(ret2); codegen.opcodes.push_back(codegen.opcodes.size() + 3); int continue_addr = codegen.opcodes.size(); codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP); @@ -1401,12 +1401,12 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Blo codegen.opcodes.push_back(cf->line); codegen.current_line = cf->line; #endif - int ret = _parse_expression(codegen, cf->arguments[0], p_stack_level, false); - if (ret < 0) + int ret2 = _parse_expression(codegen, cf->arguments[0], p_stack_level, false); + if (ret2 < 0) return ERR_PARSE_ERROR; codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP_IF_NOT); - codegen.opcodes.push_back(ret); + codegen.opcodes.push_back(ret2); int else_addr = codegen.opcodes.size(); codegen.opcodes.push_back(0); //temporary @@ -1421,9 +1421,9 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Blo codegen.opcodes.push_back(0); codegen.opcodes.write[else_addr] = codegen.opcodes.size(); - Error err = _parse_block(codegen, cf->body_else, p_stack_level, p_break_addr, p_continue_addr); - if (err) - return err; + Error err2 = _parse_block(codegen, cf->body_else, p_stack_level, p_break_addr, p_continue_addr); + if (err2) + return err2; codegen.opcodes.write[end_addr] = codegen.opcodes.size(); } else { @@ -1444,14 +1444,14 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Blo codegen.push_stack_identifiers(); codegen.add_stack_identifier(static_cast<const GDScriptParser::IdentifierNode *>(cf->arguments[0])->name, iter_stack_pos); - int ret = _parse_expression(codegen, cf->arguments[1], slevel, false); - if (ret < 0) + int ret2 = _parse_expression(codegen, cf->arguments[1], slevel, false); + if (ret2 < 0) return ERR_COMPILATION_FAILED; //assign container codegen.opcodes.push_back(GDScriptFunction::OPCODE_ASSIGN); codegen.opcodes.push_back(container_pos); - codegen.opcodes.push_back(ret); + codegen.opcodes.push_back(ret2); //begin loop codegen.opcodes.push_back(GDScriptFunction::OPCODE_ITERATE_BEGIN); @@ -1493,11 +1493,11 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Blo codegen.opcodes.push_back(0); int continue_addr = codegen.opcodes.size(); - int ret = _parse_expression(codegen, cf->arguments[0], p_stack_level, false); - if (ret < 0) + int ret2 = _parse_expression(codegen, cf->arguments[0], p_stack_level, false); + if (ret2 < 0) return ERR_PARSE_ERROR; codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP_IF_NOT); - codegen.opcodes.push_back(ret); + codegen.opcodes.push_back(ret2); codegen.opcodes.push_back(break_addr); Error err = _parse_block(codegen, cf->body, p_stack_level, break_addr, continue_addr); if (err) @@ -1508,9 +1508,6 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Blo codegen.opcodes.write[break_addr + 1] = codegen.opcodes.size(); } break; - case GDScriptParser::ControlFlowNode::CF_SWITCH: { - - } break; case GDScriptParser::ControlFlowNode::CF_BREAK: { if (p_break_addr < 0) { @@ -1536,21 +1533,21 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Blo } break; case GDScriptParser::ControlFlowNode::CF_RETURN: { - int ret; + int ret2; if (cf->arguments.size()) { - ret = _parse_expression(codegen, cf->arguments[0], p_stack_level, false); - if (ret < 0) + ret2 = _parse_expression(codegen, cf->arguments[0], p_stack_level, false); + if (ret2 < 0) return ERR_PARSE_ERROR; } else { - ret = GDScriptFunction::ADDR_TYPE_NIL << GDScriptFunction::ADDR_BITS; + ret2 = GDScriptFunction::ADDR_TYPE_NIL << GDScriptFunction::ADDR_BITS; } codegen.opcodes.push_back(GDScriptFunction::OPCODE_RETURN); - codegen.opcodes.push_back(ret); + codegen.opcodes.push_back(ret2); } break; } @@ -1561,12 +1558,12 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Blo const GDScriptParser::AssertNode *as = static_cast<const GDScriptParser::AssertNode *>(s); - int ret = _parse_expression(codegen, as->condition, p_stack_level, false); - if (ret < 0) + int ret2 = _parse_expression(codegen, as->condition, p_stack_level, false); + if (ret2 < 0) return ERR_PARSE_ERROR; codegen.opcodes.push_back(GDScriptFunction::OPCODE_ASSERT); - codegen.opcodes.push_back(ret); + codegen.opcodes.push_back(ret2); #endif } break; case GDScriptParser::Node::TYPE_BREAKPOINT: { @@ -1593,8 +1590,8 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Blo } break; default: { //expression - int ret = _parse_expression(codegen, s, p_stack_level, true); - if (ret < 0) + int ret2 = _parse_expression(codegen, s, p_stack_level, true); + if (ret2 < 0) return ERR_PARSE_ERROR; } break; } @@ -2119,8 +2116,8 @@ Error GDScriptCompiler::_parse_class_blocks(GDScript *p_script, const GDScriptPa instance->owner = E->get(); //needed for hot reloading - for (Map<StringName, GDScript::MemberInfo>::Element *E = p_script->member_indices.front(); E; E = E->next()) { - instance->member_indices_cache[E->key()] = E->get().index; + for (Map<StringName, GDScript::MemberInfo>::Element *F = p_script->member_indices.front(); F; F = F->next()) { + instance->member_indices_cache[F->key()] = F->get().index; } instance->owner->set_script_instance(instance); diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp index 08ad101967..fafc73b7e6 100644 --- a/modules/gdscript/gdscript_editor.cpp +++ b/modules/gdscript/gdscript_editor.cpp @@ -479,12 +479,15 @@ struct GDScriptCompletionContext { Object *base; String base_path; int line; + uint32_t depth; GDScriptCompletionContext() : _class(NULL), function(NULL), block(NULL), - base(NULL) {} + base(NULL), + line(0), + depth(0) {} }; struct GDScriptCompletionIdentifier { @@ -615,6 +618,9 @@ static GDScriptCompletionIdentifier _type_from_gdtype(const GDScriptDataType &p_ ci.type.script_type = p_gdtype.script_type; switch (p_gdtype.kind) { + case GDScriptDataType::UNINITIALIZED: { + ERR_EXPLAIN("Uninitialized completion. Please report a bug."); + } break; case GDScriptDataType::BUILTIN: { ci.type.kind = GDScriptParser::DataType::BUILTIN; } break; @@ -631,12 +637,18 @@ static GDScriptCompletionIdentifier _type_from_gdtype(const GDScriptDataType &p_ return ci; } -static bool _guess_identifier_type(const GDScriptCompletionContext &p_context, const StringName &p_identifier, GDScriptCompletionIdentifier &r_type); -static bool _guess_identifier_type_from_base(const GDScriptCompletionContext &p_context, const GDScriptCompletionIdentifier &p_base, const StringName &p_identifier, GDScriptCompletionIdentifier &r_type); -static bool _guess_method_return_type_from_base(const GDScriptCompletionContext &p_context, const GDScriptCompletionIdentifier &p_base, const StringName &p_method, GDScriptCompletionIdentifier &r_type); +static bool _guess_identifier_type(GDScriptCompletionContext &p_context, const StringName &p_identifier, GDScriptCompletionIdentifier &r_type); +static bool _guess_identifier_type_from_base(GDScriptCompletionContext &p_context, const GDScriptCompletionIdentifier &p_base, const StringName &p_identifier, GDScriptCompletionIdentifier &r_type); +static bool _guess_method_return_type_from_base(GDScriptCompletionContext &p_context, const GDScriptCompletionIdentifier &p_base, const StringName &p_method, GDScriptCompletionIdentifier &r_type); -static bool _guess_expression_type(const GDScriptCompletionContext &p_context, const GDScriptParser::Node *p_expression, GDScriptCompletionIdentifier &r_type) { +static bool _guess_expression_type(GDScriptCompletionContext &p_context, const GDScriptParser::Node *p_expression, GDScriptCompletionIdentifier &r_type) { bool found = false; + + if (++p_context.depth > 100) { + print_error("Maximum _guess_expression_type depth limit reached. Please file a bugreport."); + return false; + } + switch (p_expression->type) { case GDScriptParser::Node::TYPE_CONSTANT: { const GDScriptParser::ConstantNode *cn = static_cast<const GDScriptParser::ConstantNode *>(p_expression); @@ -773,12 +785,12 @@ static bool _guess_expression_type(const GDScriptCompletionContext &p_context, c if (mb && mb->is_const()) { bool all_is_const = true; Vector<Variant> args; - GDScriptCompletionContext c = p_context; - c.line = op->line; + GDScriptCompletionContext c2 = p_context; + c2.line = op->line; for (int i = 2; all_is_const && i < op->arguments.size(); i++) { GDScriptCompletionIdentifier arg; - if (_guess_expression_type(c, op->arguments[i], arg)) { + if (_guess_expression_type(c2, op->arguments[i], arg)) { if (arg.type.has_type && arg.type.is_constant && arg.value.get_type() != Variant::OBJECT) { args.push_back(arg.value); } else { @@ -1125,7 +1137,7 @@ static bool _guess_expression_type(const GDScriptCompletionContext &p_context, c return found; } -static bool _guess_identifier_type(const GDScriptCompletionContext &p_context, const StringName &p_identifier, GDScriptCompletionIdentifier &r_type) { +static bool _guess_identifier_type(GDScriptCompletionContext &p_context, const StringName &p_identifier, GDScriptCompletionIdentifier &r_type) { // Look in blocks first const GDScriptParser::BlockNode *blk = p_context.block; @@ -1270,9 +1282,9 @@ static bool _guess_identifier_type(const GDScriptCompletionContext &p_context, c for (List<MethodInfo>::Element *E = methods.front(); E; E = E->next()) { if (E->get().name == p_context.function->name) { MethodInfo &mi = E->get(); - for (List<PropertyInfo>::Element *E = mi.arguments.front(); E; E = E->next()) { - if (E->get().name == p_identifier) { - r_type = _type_from_property(E->get()); + for (List<PropertyInfo>::Element *F = mi.arguments.front(); F; F = F->next()) { + if (F->get().name == p_identifier) { + r_type = _type_from_property(F->get()); return true; } } @@ -1355,7 +1367,7 @@ static bool _guess_identifier_type(const GDScriptCompletionContext &p_context, c return false; } -static bool _guess_identifier_type_from_base(const GDScriptCompletionContext &p_context, const GDScriptCompletionIdentifier &p_base, const StringName &p_identifier, GDScriptCompletionIdentifier &r_type) { +static bool _guess_identifier_type_from_base(GDScriptCompletionContext &p_context, const GDScriptCompletionIdentifier &p_base, const StringName &p_identifier, GDScriptCompletionIdentifier &r_type) { GDScriptParser::DataType base_type = p_base.type; bool _static = base_type.is_meta_type; while (base_type.has_type) { @@ -1544,7 +1556,7 @@ static bool _find_last_return_in_block(const GDScriptCompletionContext &p_contex return false; } -static bool _guess_method_return_type_from_base(const GDScriptCompletionContext &p_context, const GDScriptCompletionIdentifier &p_base, const StringName &p_method, GDScriptCompletionIdentifier &r_type) { +static bool _guess_method_return_type_from_base(GDScriptCompletionContext &p_context, const GDScriptCompletionIdentifier &p_base, const StringName &p_method, GDScriptCompletionIdentifier &r_type) { GDScriptParser::DataType base_type = p_base.type; bool _static = base_type.is_meta_type; @@ -2225,8 +2237,8 @@ static void _find_call_arguments(const GDScriptCompletionContext &p_context, con if (obj) { List<String> options; obj->get_argument_options(p_method, p_argidx, &options); - for (List<String>::Element *E = options.front(); E; E = E->next()) { - r_result.insert(E->get()); + for (List<String>::Element *F = options.front(); F; F = F->next()) { + r_result.insert(F->get()); } } } @@ -2309,7 +2321,7 @@ static void _find_call_arguments(const GDScriptCompletionContext &p_context, con } } -static void _find_call_arguments(const GDScriptCompletionContext &p_context, const GDScriptParser::Node *p_node, int p_argidx, Set<String> &r_result, bool &r_forced, String &r_arghint) { +static void _find_call_arguments(GDScriptCompletionContext &p_context, const GDScriptParser::Node *p_node, int p_argidx, Set<String> &r_result, bool &r_forced, String &r_arghint) { if (!p_node || p_node->type != GDScriptParser::Node::TYPE_OPERATOR) { return; @@ -2794,12 +2806,12 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_base if (base_type.class_type) { for (Map<StringName, GDScriptParser::ClassNode::Constant>::Element *E = base_type.class_type->constant_expressions.front(); E; E = E->next()) { GDScriptCompletionIdentifier constant; - GDScriptCompletionContext c = context; - c._class = base_type.class_type; - c.function = NULL; - c.block = NULL; - c.line = E->value().expression->line; - if (_guess_expression_type(c, E->value().expression, constant)) { + GDScriptCompletionContext c2 = context; + c2._class = base_type.class_type; + c2.function = NULL; + c2.block = NULL; + c2.line = E->value().expression->line; + if (_guess_expression_type(c2, E->value().expression, constant)) { if (constant.type.has_type && constant.type.is_meta_type) { options.insert(E->key().operator String()); } diff --git a/modules/gdscript/gdscript_function.cpp b/modules/gdscript/gdscript_function.cpp index 966c02d4ec..98871ddec3 100644 --- a/modules/gdscript/gdscript_function.cpp +++ b/modules/gdscript/gdscript_function.cpp @@ -1083,7 +1083,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a if (argc >= 1) { methodstr = String(*argptrs[0]) + " (via call)"; if (err.error == Variant::CallError::CALL_ERROR_INVALID_ARGUMENT) { - err.argument -= 1; + err.argument += 1; } } } else if (methodstr == "free") { diff --git a/modules/gdscript/gdscript_function.h b/modules/gdscript/gdscript_function.h index f4058664ff..cefc28d77f 100644 --- a/modules/gdscript/gdscript_function.h +++ b/modules/gdscript/gdscript_function.h @@ -36,7 +36,7 @@ #include "core/reference.h" #include "core/script_language.h" #include "core/self_list.h" -#include "core/string_db.h" +#include "core/string_name.h" #include "core/variant.h" class GDScriptInstance; @@ -45,10 +45,11 @@ class GDScript; struct GDScriptDataType { bool has_type; enum { + UNINITIALIZED, BUILTIN, NATIVE, SCRIPT, - GDSCRIPT + GDSCRIPT, } kind; Variant::Type builtin_type; StringName native_type; @@ -58,6 +59,8 @@ struct GDScriptDataType { if (!has_type) return true; // Can't type check switch (kind) { + case UNINITIALIZED: + break; case BUILTIN: { Variant::Type var_type = p_variant.get_type(); bool valid = builtin_type == var_type; @@ -113,6 +116,8 @@ struct GDScriptDataType { PropertyInfo info; if (has_type) { switch (kind) { + case UNINITIALIZED: + break; case BUILTIN: { info.type = builtin_type; } break; @@ -134,7 +139,9 @@ struct GDScriptDataType { } GDScriptDataType() : - has_type(false) {} + has_type(false), + kind(UNINITIALIZED), + builtin_type(Variant::NIL) {} }; class GDScriptFunction { diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index af189fdb7e..705f39ae78 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -503,7 +503,7 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s Ref<GDScript> gds = res; if (gds.is_valid() && !gds->is_valid()) { - _set_error("Could not fully preload the script, possible cyclic reference or compilation error."); + _set_error("Could not fully preload the script, possible cyclic reference or compilation error. Use 'load()' instead if a cyclic reference is intended."); return NULL; } @@ -2640,14 +2640,14 @@ void GDScriptParser::_transform_match_statment(MatchNode *p_match_statement) { local_var->assign = e->value(); local_var->set_datatype(local_var->assign->get_datatype()); - IdentifierNode *id = alloc_node<IdentifierNode>(); - id->name = local_var->name; - id->declared_block = branch->body; - id->set_datatype(local_var->assign->get_datatype()); + IdentifierNode *id2 = alloc_node<IdentifierNode>(); + id2->name = local_var->name; + id2->declared_block = branch->body; + id2->set_datatype(local_var->assign->get_datatype()); OperatorNode *op = alloc_node<OperatorNode>(); op->op = OperatorNode::OP_ASSIGN; - op->arguments.push_back(id); + op->arguments.push_back(id2); op->arguments.push_back(local_var->assign); branch->body->statements.push_front(op); @@ -2694,9 +2694,9 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) { if (pending_newline != -1) { - NewLineNode *nl = alloc_node<NewLineNode>(); - nl->line = pending_newline; - p_block->statements.push_back(nl); + NewLineNode *nl2 = alloc_node<NewLineNode>(); + nl2->line = pending_newline; + p_block->statements.push_back(nl2); pending_newline = -1; } @@ -2735,9 +2735,9 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) { return; } - NewLineNode *nl = alloc_node<NewLineNode>(); - nl->line = tokenizer->get_token_line(); - p_block->statements.push_back(nl); + NewLineNode *nl2 = alloc_node<NewLineNode>(); + nl2->line = tokenizer->get_token_line(); + p_block->statements.push_back(nl2); } break; case GDScriptTokenizer::TK_CF_PASS: { @@ -2922,14 +2922,14 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) { cf_else->cf_type = ControlFlowNode::CF_IF; //condition - Node *condition = _parse_and_reduce_expression(p_block, p_static); - if (!condition) { + Node *condition2 = _parse_and_reduce_expression(p_block, p_static); + if (!condition2) { if (_recover_from_completion()) { break; } return; } - cf_else->arguments.push_back(condition); + cf_else->arguments.push_back(condition2); cf_else->cf_type = ControlFlowNode::CF_IF; cf_if->body_else->statements.push_back(cf_else); @@ -2992,8 +2992,8 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) { case GDScriptTokenizer::TK_CF_WHILE: { tokenizer->advance(); - Node *condition = _parse_and_reduce_expression(p_block, p_static); - if (!condition) { + Node *condition2 = _parse_and_reduce_expression(p_block, p_static); + if (!condition2) { if (_recover_from_completion()) { break; } @@ -3003,7 +3003,7 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) { ControlFlowNode *cf_while = alloc_node<ControlFlowNode>(); cf_while->cf_type = ControlFlowNode::CF_WHILE; - cf_while->arguments.push_back(condition); + cf_while->arguments.push_back(condition2); cf_while->body = alloc_node<BlockNode>(); cf_while->body->parent_block = p_block; @@ -3494,16 +3494,20 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { tokenizer->advance(); if ((tokenizer->get_token() == GDScriptTokenizer::TK_CONSTANT && tokenizer->get_token_constant().get_type() == Variant::STRING)) { - Variant constant = tokenizer->get_token_constant(); - String icon_path = constant.operator String(); +#ifdef TOOLS_ENABLED + if (Engine::get_singleton()->is_editor_hint()) { + Variant constant = tokenizer->get_token_constant(); + String icon_path = constant.operator String(); - String abs_icon_path = icon_path.is_rel_path() ? self_path.get_base_dir().plus_file(icon_path).simplify_path() : icon_path; - if (!FileAccess::exists(abs_icon_path)) { - _set_error("No class icon found at: " + abs_icon_path); - return; - } + String abs_icon_path = icon_path.is_rel_path() ? self_path.get_base_dir().plus_file(icon_path).simplify_path() : icon_path; + if (!FileAccess::exists(abs_icon_path)) { + _set_error("No class icon found at: " + abs_icon_path); + return; + } - p_class->icon_path = icon_path; + p_class->icon_path = icon_path; + } +#endif tokenizer->advance(); } else { @@ -4553,6 +4557,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { //variale declaration and (eventual) initialization ClassNode::Member member; + bool autoexport = tokenizer->get_token(-1) == GDScriptTokenizer::TK_PR_EXPORT; if (current_export.type != Variant::NIL) { member._export = current_export; @@ -4700,12 +4705,12 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { op->arguments.push_back(subexpr); #ifdef DEBUG_ENABLED - NewLineNode *nl = alloc_node<NewLineNode>(); - nl->line = line; + NewLineNode *nl2 = alloc_node<NewLineNode>(); + nl2->line = line; if (onready) - p_class->ready->statements.push_back(nl); + p_class->ready->statements.push_back(nl2); else - p_class->initializer->statements.push_back(nl); + p_class->initializer->statements.push_back(nl2); #endif if (onready) p_class->ready->statements.push_back(op); @@ -4720,6 +4725,25 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { _set_error("Type-less export needs a constant expression assigned to infer type."); return; } + + if (member._export.type != Variant::NIL) { + IdentifierNode *id = alloc_node<IdentifierNode>(); + id->name = member.identifier; + + ConstantNode *cn = alloc_node<ConstantNode>(); + + Variant::CallError ce2; + cn->value = Variant::construct(member._export.type, NULL, 0, ce2); + + OperatorNode *op = alloc_node<OperatorNode>(); + op->op = OperatorNode::OP_INIT_ASSIGN; + op->arguments.push_back(id); + op->arguments.push_back(cn); + + p_class->initializer->statements.push_back(op); + + member.initial_assignment = op; + } } if (autoexport && member.data_type.has_type) { @@ -5499,10 +5523,10 @@ GDScriptParser::DataType GDScriptParser::_resolve_type(const DataType &p_source, result.script_type = gds; found = true; } else { - Ref<Script> scr = constants[id]; - if (scr.is_valid()) { + Ref<Script> scr2 = constants[id]; + if (scr2.is_valid()) { result.kind = DataType::SCRIPT; - result.script_type = scr; + result.script_type = scr2; found = true; } } @@ -5594,6 +5618,9 @@ GDScriptParser::DataType GDScriptParser::_type_from_gdtype(const GDScriptDataTyp result.script_type = p_gdtype.script_type; switch (p_gdtype.kind) { + case GDScriptDataType::UNINITIALIZED: { + ERR_EXPLAIN("Uninitialized datatype. Please report a bug."); + } break; case GDScriptDataType::BUILTIN: { result.kind = DataType::BUILTIN; } break; @@ -6619,7 +6646,7 @@ GDScriptParser::DataType GDScriptParser::_reduce_function_call_type(const Operat bool match = false; List<MethodInfo> constructors; Variant::get_constructor_list(tn->vtype, &constructors); - PropertyInfo return_type; + PropertyInfo return_type2; for (List<MethodInfo>::Element *E = constructors.front(); E; E = E->next()) { MethodInfo &mi = E->get(); @@ -6658,13 +6685,13 @@ GDScriptParser::DataType GDScriptParser::_reduce_function_call_type(const Operat if (types_match) { match = true; - return_type = mi.return_val; + return_type2 = mi.return_val; break; } } if (match) { - return _type_from_property(return_type, false); + return _type_from_property(return_type2, false); } else if (check_types) { String err = "No constructor of '"; err += Variant::get_type_name(tn->vtype); @@ -6795,7 +6822,7 @@ GDScriptParser::DataType GDScriptParser::_reduce_function_call_type(const Operat return_type = original_type; return_type.is_meta_type = false; - valid = true; // There's always an initializer, we can asume this is true + valid = true; // There's always an initializer, we can assume this is true } if (!valid) { @@ -7576,7 +7603,7 @@ void GDScriptParser::_check_function_types(FunctionNode *p_function) { } parent_signature += " " + p_function->name + "("; if (arg_types.size()) { - int i = 0; + int j = 0; for (List<DataType>::Element *E = arg_types.front(); E; E = E->next()) { if (E != arg_types.front()) { parent_signature += ", "; @@ -7586,11 +7613,11 @@ void GDScriptParser::_check_function_types(FunctionNode *p_function) { arg = "Variant"; } parent_signature += arg; - if (i == arg_types.size() - default_arg_count) { + if (j == arg_types.size() - default_arg_count) { parent_signature += "=default"; } - i++; + j++; } } parent_signature += ")"; diff --git a/modules/gdscript/gdscript_parser.h b/modules/gdscript/gdscript_parser.h index b4a705c9e7..5ded4668a7 100644 --- a/modules/gdscript/gdscript_parser.h +++ b/modules/gdscript/gdscript_parser.h @@ -95,6 +95,7 @@ public: } DataType() : + kind(UNRESOLVED), has_type(false), is_constant(false), is_meta_type(false), @@ -168,6 +169,7 @@ public: MultiplayerAPI::RPCMode rpc_mode; int usages; }; + struct Constant { Node *expression; DataType type; @@ -443,7 +445,6 @@ public: CF_IF, CF_FOR, CF_WHILE, - CF_SWITCH, CF_BREAK, CF_CONTINUE, CF_RETURN, diff --git a/modules/gdscript/gdscript_tokenizer.cpp b/modules/gdscript/gdscript_tokenizer.cpp index 127a00a9f3..480bf0fa3c 100644 --- a/modules/gdscript/gdscript_tokenizer.cpp +++ b/modules/gdscript/gdscript_tokenizer.cpp @@ -80,10 +80,7 @@ const char *GDScriptTokenizer::token_names[TK_MAX] = { "elif", "else", "for", - "do", "while", - "switch (reserved)", - "case (reserved)", "break", "continue", "pass", @@ -224,9 +221,6 @@ static const _kws _keyword_list[] = { { GDScriptTokenizer::TK_CF_ELSE, "else" }, { GDScriptTokenizer::TK_CF_FOR, "for" }, { GDScriptTokenizer::TK_CF_WHILE, "while" }, - { GDScriptTokenizer::TK_CF_DO, "do" }, - { GDScriptTokenizer::TK_CF_SWITCH, "switch" }, - { GDScriptTokenizer::TK_CF_CASE, "case" }, { GDScriptTokenizer::TK_CF_BREAK, "break" }, { GDScriptTokenizer::TK_CF_CONTINUE, "continue" }, { GDScriptTokenizer::TK_CF_RETURN, "return" }, @@ -291,9 +285,6 @@ bool GDScriptTokenizer::is_token_literal(int p_offset, bool variable_safe) const case TK_CF_ELSE: case TK_CF_FOR: case TK_CF_WHILE: - case TK_CF_DO: - case TK_CF_SWITCH: - case TK_CF_CASE: case TK_CF_BREAK: case TK_CF_CONTINUE: case TK_CF_RETURN: @@ -998,11 +989,11 @@ void GDScriptTokenizerText::_advance() { //built in func? - for (int i = 0; i < GDScriptFunctions::FUNC_MAX; i++) { + for (int j = 0; j < GDScriptFunctions::FUNC_MAX; j++) { - if (str == GDScriptFunctions::get_func_name(GDScriptFunctions::Function(i))) { + if (str == GDScriptFunctions::get_func_name(GDScriptFunctions::Function(j))) { - _make_built_in_func(GDScriptFunctions::Function(i)); + _make_built_in_func(GDScriptFunctions::Function(j)); found = true; break; } @@ -1426,7 +1417,7 @@ StringName GDScriptTokenizerBuffer::get_token_identifier(int p_offset) const { ERR_FAIL_INDEX_V(offset, tokens.size(), StringName()); uint32_t identifier = tokens[offset] >> TOKEN_BITS; - ERR_FAIL_INDEX_V(identifier, (uint32_t)identifiers.size(), StringName()); + ERR_FAIL_UNSIGNED_INDEX_V(identifier, identifiers.size(), StringName()); return identifiers[identifier]; } @@ -1482,7 +1473,7 @@ const Variant &GDScriptTokenizerBuffer::get_token_constant(int p_offset) const { int offset = token + p_offset; ERR_FAIL_INDEX_V(offset, tokens.size(), nil); uint32_t constant = tokens[offset] >> TOKEN_BITS; - ERR_FAIL_INDEX_V(constant, (uint32_t)constants.size(), nil); + ERR_FAIL_UNSIGNED_INDEX_V(constant, constants.size(), nil); return constants[constant]; } String GDScriptTokenizerBuffer::get_token_error(int p_offset) const { diff --git a/modules/gdscript/gdscript_tokenizer.h b/modules/gdscript/gdscript_tokenizer.h index abacdf0322..7b977ff67c 100644 --- a/modules/gdscript/gdscript_tokenizer.h +++ b/modules/gdscript/gdscript_tokenizer.h @@ -32,7 +32,7 @@ #define GDSCRIPT_TOKENIZER_H #include "core/pair.h" -#include "core/string_db.h" +#include "core/string_name.h" #include "core/ustring.h" #include "core/variant.h" #include "core/vmap.h" @@ -86,10 +86,7 @@ public: TK_CF_ELIF, TK_CF_ELSE, TK_CF_FOR, - TK_CF_DO, TK_CF_WHILE, - TK_CF_SWITCH, - TK_CF_CASE, TK_CF_BREAK, TK_CF_CONTINUE, TK_CF_PASS, @@ -118,7 +115,7 @@ public: TK_PR_REMOTE, TK_PR_SYNC, TK_PR_MASTER, - TK_PR_SLAVE, + TK_PR_SLAVE, // Deprecated by TK_PR_PUPPET, to remove in 4.0 TK_PR_PUPPET, TK_PR_REMOTESYNC, TK_PR_MASTERSYNC, @@ -176,7 +173,7 @@ public: #ifdef DEBUG_ENABLED virtual const Vector<Pair<int, String> > &get_warning_skips() const = 0; virtual const Set<String> &get_warning_global_skips() const = 0; - virtual const bool is_ignoring_warnings() const = 0; + virtual bool is_ignoring_warnings() const = 0; #endif // DEBUG_ENABLED virtual ~GDScriptTokenizer(){}; @@ -248,7 +245,7 @@ public: #ifdef DEBUG_ENABLED virtual const Vector<Pair<int, String> > &get_warning_skips() const { return warning_skips; } virtual const Set<String> &get_warning_global_skips() const { return warning_global_skips; } - virtual const bool is_ignoring_warnings() const { return ignore_warnings; } + virtual bool is_ignoring_warnings() const { return ignore_warnings; } #endif // DEBUG_ENABLED }; @@ -292,7 +289,7 @@ public: static Set<String> s; return s; } - virtual const bool is_ignoring_warnings() const { return true; } + virtual bool is_ignoring_warnings() const { return true; } #endif // DEBUG_ENABLED GDScriptTokenizerBuffer(); }; diff --git a/modules/gridmap/grid_map_editor_plugin.cpp b/modules/gridmap/grid_map_editor_plugin.cpp index 12c4a18a64..bc7a576785 100644 --- a/modules/gridmap/grid_map_editor_plugin.cpp +++ b/modules/gridmap/grid_map_editor_plugin.cpp @@ -289,11 +289,11 @@ void GridMapEditor::_update_selection_transform() { scale *= node->get_cell_size(); pos *= node->get_cell_size(); - Transform xf; - xf.basis.scale(scale); - xf.origin = pos; + Transform xf2; + xf2.basis.scale(scale); + xf2.origin = pos; - VisualServer::get_singleton()->instance_set_transform(selection_level_instance[i], xf); + VisualServer::get_singleton()->instance_set_transform(selection_level_instance[i], xf2); } } } @@ -631,7 +631,7 @@ bool GridMapEditor::forward_spatial_input_event(Camera *p_camera, const Ref<Inpu (mb->get_button_index() == BUTTON_LEFT && input_action == INPUT_PAINT)) { if (set_items.size()) { - undo_redo->create_action("GridMap Paint"); + undo_redo->create_action(TTR("GridMap Paint")); for (List<SetItem>::Element *E = set_items.front(); E; E = E->next()) { const SetItem &si = E->get(); diff --git a/modules/mbedtls/stream_peer_mbed_tls.cpp b/modules/mbedtls/stream_peer_mbed_tls.cpp index 973713f500..45d3b86919 100755 --- a/modules/mbedtls/stream_peer_mbed_tls.cpp +++ b/modules/mbedtls/stream_peer_mbed_tls.cpp @@ -270,7 +270,10 @@ void StreamPeerMbedTLS::poll() { return; } - int ret = mbedtls_ssl_read(&ssl, NULL, 0); + // We could pass NULL as second parameter, but some behaviour sanitizers doesn't seem to like that. + // Passing a 1 byte buffer to workaround it. + uint8_t byte; + int ret = mbedtls_ssl_read(&ssl, &byte, 0); if (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE) { // Nothing to read/write (non blocking IO) @@ -313,7 +316,7 @@ void StreamPeerMbedTLS::disconnect_from_stream() { Ref<StreamPeerTCP> tcp = base; if (tcp.is_valid() && tcp->get_status() == StreamPeerTCP::STATUS_CONNECTED) { - // We are still connected on the socket, try to send close notity. + // We are still connected on the socket, try to send close notify. mbedtls_ssl_close_notify(&ssl); } diff --git a/modules/mobile_vr/mobile_vr_interface.cpp b/modules/mobile_vr/mobile_vr_interface.cpp index 78cc667718..b4fbd417d7 100644 --- a/modules/mobile_vr/mobile_vr_interface.cpp +++ b/modules/mobile_vr/mobile_vr_interface.cpp @@ -31,7 +31,7 @@ #include "mobile_vr_interface.h" #include "core/os/input.h" #include "core/os/os.h" -#include "servers/visual/visual_server_global.h" +#include "servers/visual/visual_server_globals.h" StringName MobileVRInterface::get_name() const { return "Native mobile"; diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp index 5da1344595..51615df64e 100644 --- a/modules/mono/csharp_script.cpp +++ b/modules/mono/csharp_script.cpp @@ -719,13 +719,13 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) { // Script::instances are deleted during managed object disposal, which happens on domain finalize. // Only placeholders are kept. Therefore we need to keep a copy before that happens. - for (Set<Object *>::Element *E = script->instances.front(); E; E = E->next()) { - script->pending_reload_instances.insert(E->get()->get_instance_id()); + for (Set<Object *>::Element *F = script->instances.front(); F; F = F->next()) { + script->pending_reload_instances.insert(F->get()->get_instance_id()); } #ifdef TOOLS_ENABLED - for (Set<PlaceHolderScriptInstance *>::Element *E = script->placeholders.front(); E; E = E->next()) { - script->pending_reload_instances.insert(E->get()->get_owner()->get_instance_id()); + for (Set<PlaceHolderScriptInstance *>::Element *F = script->placeholders.front(); F; F = F->next()) { + script->pending_reload_instances.insert(F->get()->get_owner()->get_instance_id()); } #endif @@ -1113,19 +1113,23 @@ bool CSharpLanguage::setup_csharp_script_binding(CSharpScriptBinding &r_script_b void *CSharpLanguage::alloc_instance_binding_data(Object *p_object) { + SCOPED_MUTEX_LOCK(language_bind_mutex); + + Map<Object *, CSharpScriptBinding>::Element *match = script_bindings.find(p_object); + if (match) + return (void *)match; + CSharpScriptBinding script_binding; if (!setup_csharp_script_binding(script_binding, p_object)) return NULL; - void *data; + return (void *)insert_script_binding(p_object, script_binding); +} - { - SCOPED_MUTEX_LOCK(language_bind_mutex); - data = (void *)script_bindings.insert(p_object, script_binding); - } +Map<Object *, CSharpScriptBinding>::Element *CSharpLanguage::insert_script_binding(Object *p_object, const CSharpScriptBinding &p_script_binding) { - return data; + return script_bindings.insert(p_object, p_script_binding); } void CSharpLanguage::free_instance_binding_data(void *p_data) { @@ -2279,17 +2283,18 @@ void CSharpScript::_bind_methods() { ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "new", &CSharpScript::_new, MethodInfo(Variant::OBJECT, "new")); } -Ref<CSharpScript> CSharpScript::create_for_managed_type(GDMonoClass *p_class) { +Ref<CSharpScript> CSharpScript::create_for_managed_type(GDMonoClass *p_class, GDMonoClass *p_native) { // This method should not fail CRASH_COND(!p_class); + // TODO: Cache the 'CSharpScript' associated with this 'p_class' instead of allocating a new one every time Ref<CSharpScript> script = memnew(CSharpScript); script->name = p_class->get_name(); script->script_class = p_class; - script->native = GDMonoUtils::get_class_native_base(script->script_class); + script->native = p_native; CRASH_COND(script->native == NULL); diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h index db9d6a73a2..8b1a4b5f7e 100644 --- a/modules/mono/csharp_script.h +++ b/modules/mono/csharp_script.h @@ -135,7 +135,7 @@ class CSharpScript : public Script { // Do not use unless you know what you are doing friend void GDMonoInternals::tie_managed_to_unmanaged(MonoObject *, Object *); - static Ref<CSharpScript> create_for_managed_type(GDMonoClass *p_class); + static Ref<CSharpScript> create_for_managed_type(GDMonoClass *p_class, GDMonoClass *p_native); protected: static void _bind_methods(); @@ -312,6 +312,8 @@ class CSharpLanguage : public ScriptLanguage { public: StringNameCache string_names; + Mutex *get_language_bind_mutex() { return language_bind_mutex; } + _FORCE_INLINE_ int get_language_index() { return lang_idx; } void set_language_index(int p_idx); @@ -406,6 +408,7 @@ public: virtual void refcount_incremented_instance_binding(Object *p_object); virtual bool refcount_decremented_instance_binding(Object *p_object); + Map<Object *, CSharpScriptBinding>::Element *insert_script_binding(Object *p_object, const CSharpScriptBinding &p_script_binding); bool setup_csharp_script_binding(CSharpScriptBinding &r_script_binding, Object *p_object); #ifdef DEBUG_ENABLED diff --git a/modules/mono/editor/GodotSharpTools/Build/BuildSystem.cs b/modules/mono/editor/GodotSharpTools/Build/BuildSystem.cs index 4137f5eaef..e7d0486c76 100644 --- a/modules/mono/editor/GodotSharpTools/Build/BuildSystem.cs +++ b/modules/mono/editor/GodotSharpTools/Build/BuildSystem.cs @@ -18,8 +18,6 @@ namespace GodotSharpTools.Build [MethodImpl(MethodImplOptions.InternalCall)] private extern static string godot_icall_BuildInstance_get_MSBuildPath(); [MethodImpl(MethodImplOptions.InternalCall)] - private extern static string godot_icall_BuildInstance_get_FrameworkPath(); - [MethodImpl(MethodImplOptions.InternalCall)] private extern static string godot_icall_BuildInstance_get_MonoWindowsBinDir(); [MethodImpl(MethodImplOptions.InternalCall)] private extern static bool godot_icall_BuildInstance_get_UsingMonoMSBuildOnWindows(); @@ -34,11 +32,6 @@ namespace GodotSharpTools.Build return msbuildPath; } - private static string GetFrameworkPath() - { - return godot_icall_BuildInstance_get_FrameworkPath(); - } - private static string MonoWindowsBinDir { get @@ -85,11 +78,6 @@ namespace GodotSharpTools.Build if (customProperties != null) customPropertiesList.AddRange(customProperties); - string frameworkPath = GetFrameworkPath(); - - if (!string.IsNullOrEmpty(frameworkPath)) - customPropertiesList.Add("FrameworkPathOverride=" + frameworkPath); - string compilerArgs = BuildArguments(loggerAssemblyPath, loggerOutputDir, customPropertiesList); ProcessStartInfo startInfo = new ProcessStartInfo(GetMSBuildPath(), compilerArgs); @@ -145,11 +133,6 @@ namespace GodotSharpTools.Build if (customProperties != null) customPropertiesList.AddRange(customProperties); - string frameworkPath = GetFrameworkPath(); - - if (!string.IsNullOrEmpty(frameworkPath)) - customPropertiesList.Add("FrameworkPathOverride=" + frameworkPath); - string compilerArgs = BuildArguments(loggerAssemblyPath, loggerOutputDir, customPropertiesList); ProcessStartInfo startInfo = new ProcessStartInfo(GetMSBuildPath(), compilerArgs); diff --git a/modules/mono/editor/GodotSharpTools/GodotSharpTools.csproj b/modules/mono/editor/GodotSharpTools/GodotSharpTools.csproj index f9e9f41977..9a5dd24bb1 100644 --- a/modules/mono/editor/GodotSharpTools/GodotSharpTools.csproj +++ b/modules/mono/editor/GodotSharpTools/GodotSharpTools.csproj @@ -8,6 +8,7 @@ <RootNamespace>GodotSharpTools</RootNamespace> <AssemblyName>GodotSharpTools</AssemblyName> <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> + <BaseIntermediateOutputPath>obj</BaseIntermediateOutputPath> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <DebugSymbols>true</DebugSymbols> diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp index 0b6a6a327c..cffccd5cb5 100644 --- a/modules/mono/editor/bindings_generator.cpp +++ b/modules/mono/editor/bindings_generator.cpp @@ -97,7 +97,7 @@ #define C_METHOD_MONOARRAY_TO(m_type) C_NS_MONOMARSHAL "::mono_array_to_" #m_type #define C_METHOD_MONOARRAY_FROM(m_type) C_NS_MONOMARSHAL "::" #m_type "_to_mono_array" -#define BINDINGS_GENERATOR_VERSION UINT32_C(6) +#define BINDINGS_GENERATOR_VERSION UINT32_C(7) const char *BindingsGenerator::TypeInterface::DEFAULT_VARARG_C_IN = "\t%0 %1_in = %1;\n"; @@ -365,8 +365,8 @@ void BindingsGenerator::_generate_global_constants(List<String> &p_output) { p_output.push_back(enum_proxy_name); p_output.push_back("\n" INDENT1 OPEN_BLOCK); - for (const List<ConstantInterface>::Element *E = ienum.constants.front(); E; E = E->next()) { - const ConstantInterface &iconstant = E->get(); + for (const List<ConstantInterface>::Element *F = ienum.constants.front(); F; F = F->next()) { + const ConstantInterface &iconstant = F->get(); if (iconstant.const_doc && iconstant.const_doc->description.size()) { p_output.push_back(INDENT2 "/// <summary>\n"); @@ -389,7 +389,7 @@ void BindingsGenerator::_generate_global_constants(List<String> &p_output) { p_output.push_back(iconstant.proxy_name); p_output.push_back(" = "); p_output.push_back(itos(iconstant.value)); - p_output.push_back(E != ienum.constants.back() ? ",\n" : "\n"); + p_output.push_back(F != ienum.constants.back() ? ",\n" : "\n"); } p_output.push_back(INDENT1 CLOSE_BLOCK); @@ -472,8 +472,6 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_solution_dir, String output_dir = output_file.get_base_dir(); if (!DirAccess::exists(output_dir)) { - DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); - ERR_FAIL_COND_V(!da, ERR_CANT_CREATE); Error err = da->make_dir_recursive(ProjectSettings::get_singleton()->globalize_path(output_dir)); ERR_FAIL_COND_V(err != OK, ERR_CANT_CREATE); } @@ -806,8 +804,8 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str output.push_back(ienum.cname.operator String()); output.push_back(MEMBER_BEGIN OPEN_BLOCK); - for (const List<ConstantInterface>::Element *E = ienum.constants.front(); E; E = E->next()) { - const ConstantInterface &iconstant = E->get(); + for (const List<ConstantInterface>::Element *F = ienum.constants.front(); F; F = F->next()) { + const ConstantInterface &iconstant = F->get(); if (iconstant.const_doc && iconstant.const_doc->description.size()) { output.push_back(INDENT3 "/// <summary>\n"); @@ -830,7 +828,7 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str output.push_back(iconstant.proxy_name); output.push_back(" = "); output.push_back(itos(iconstant.value)); - output.push_back(E != ienum.constants.back() ? ",\n" : "\n"); + output.push_back(F != ienum.constants.back() ? ",\n" : "\n"); } output.push_back(INDENT2 CLOSE_BLOCK); @@ -849,9 +847,17 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str } } + // TODO: BINDINGS_NATIVE_NAME_FIELD should be StringName, once we support it in C# + if (itype.is_singleton) { // Add the type name and the singleton pointer as static fields + output.push_back(MEMBER_BEGIN "private static Godot.Object singleton;\n"); + output.push_back(MEMBER_BEGIN "public static Godot.Object Singleton\n" INDENT2 "{\n" INDENT3 + "get\n" INDENT3 "{\n" INDENT4 "if (singleton == null)\n" INDENT5 + "singleton = Engine.GetSingleton(" BINDINGS_NATIVE_NAME_FIELD ");\n" INDENT4 + "return singleton;\n" INDENT3 "}\n" INDENT2 "}\n"); + output.push_back(MEMBER_BEGIN "private const string " BINDINGS_NATIVE_NAME_FIELD " = \""); output.push_back(itype.name); output.push_back("\";\n"); @@ -1881,8 +1887,8 @@ void BindingsGenerator::_populate_object_type_interfaces() { } if (!imethod.is_virtual && imethod.name[0] == '_') { - for (const List<PropertyInterface>::Element *E = itype.properties.front(); E; E = E->next()) { - const PropertyInterface &iprop = E->get(); + for (const List<PropertyInterface>::Element *F = itype.properties.front(); F; F = F->next()) { + const PropertyInterface &iprop = F->get(); if (iprop.setter == imethod.name || iprop.getter == imethod.name) { imethod.is_internal = true; @@ -2344,9 +2350,9 @@ void BindingsGenerator::_populate_global_constants() { if (enum_name != StringName()) { EnumInterface ienum(enum_name); - List<EnumInterface>::Element *match = global_enums.find(ienum); - if (match) { - match->get().constants.push_back(iconstant); + List<EnumInterface>::Element *enum_match = global_enums.find(ienum); + if (enum_match) { + enum_match->get().constants.push_back(iconstant); } else { ienum.constants.push_back(iconstant); global_enums.push_back(ienum); diff --git a/modules/mono/editor/godotsharp_builds.cpp b/modules/mono/editor/godotsharp_builds.cpp index a040e4a344..5e1c9875f0 100644 --- a/modules/mono/editor/godotsharp_builds.cpp +++ b/modules/mono/editor/godotsharp_builds.cpp @@ -100,22 +100,24 @@ MonoString *godot_icall_BuildInstance_get_MSBuildPath() { if (msbuild_tools_path.empty() || !FileAccess::exists(msbuild_tools_path)) { // Try to search it again if it wasn't found last time or if it was removed from its location msbuild_tools_path = MonoRegUtils::find_msbuild_tools_path(); - } - - if (msbuild_tools_path.length()) { - if (!msbuild_tools_path.ends_with("\\")) - msbuild_tools_path += "\\"; - return GDMonoMarshal::mono_string_from_godot(msbuild_tools_path + "MSBuild.exe"); + if (msbuild_tools_path.empty()) { + ERR_PRINTS("Cannot find executable for '" PROP_NAME_MSBUILD_VS "'. Tried with path: " + msbuild_tools_path); + return NULL; + } } - print_verbose("Cannot find executable for '" PROP_NAME_MSBUILD_VS "'. Trying with '" PROP_NAME_MSBUILD_MONO "'..."); - } // FALL THROUGH + if (!msbuild_tools_path.ends_with("\\")) + msbuild_tools_path += "\\"; + + return GDMonoMarshal::mono_string_from_godot(msbuild_tools_path + "MSBuild.exe"); + } break; case GodotSharpBuilds::MSBUILD_MONO: { String msbuild_path = GDMono::get_singleton()->get_mono_reg_info().bin_dir.plus_file("msbuild.bat"); if (!FileAccess::exists(msbuild_path)) { - WARN_PRINTS("Cannot find executable for '" PROP_NAME_MSBUILD_MONO "'. Tried with path: " + msbuild_path); + ERR_PRINTS("Cannot find executable for '" PROP_NAME_MSBUILD_MONO "'. Tried with path: " + msbuild_path); + return NULL; } return GDMonoMarshal::mono_string_from_godot(msbuild_path); @@ -124,7 +126,8 @@ MonoString *godot_icall_BuildInstance_get_MSBuildPath() { String xbuild_path = GDMono::get_singleton()->get_mono_reg_info().bin_dir.plus_file("xbuild.bat"); if (!FileAccess::exists(xbuild_path)) { - WARN_PRINTS("Cannot find executable for '" PROP_NAME_XBUILD "'. Tried with path: " + xbuild_path); + ERR_PRINTS("Cannot find executable for '" PROP_NAME_XBUILD "'. Tried with path: " + xbuild_path); + return NULL; } return GDMonoMarshal::mono_string_from_godot(xbuild_path); @@ -144,7 +147,7 @@ MonoString *godot_icall_BuildInstance_get_MSBuildPath() { } if (xbuild_path.empty()) { - WARN_PRINT("Cannot find binary for '" PROP_NAME_XBUILD "'"); + ERR_PRINT("Cannot find binary for '" PROP_NAME_XBUILD "'"); return NULL; } } else { @@ -154,7 +157,7 @@ MonoString *godot_icall_BuildInstance_get_MSBuildPath() { } if (msbuild_path.empty()) { - WARN_PRINT("Cannot find binary for '" PROP_NAME_MSBUILD_MONO "'"); + ERR_PRINT("Cannot find binary for '" PROP_NAME_MSBUILD_MONO "'"); return NULL; } } @@ -168,22 +171,6 @@ MonoString *godot_icall_BuildInstance_get_MSBuildPath() { #endif } -MonoString *godot_icall_BuildInstance_get_FrameworkPath() { - -#if defined(WINDOWS_ENABLED) - const MonoRegInfo &mono_reg_info = GDMono::get_singleton()->get_mono_reg_info(); - if (mono_reg_info.assembly_dir.length()) { - String framework_path = path_join(mono_reg_info.assembly_dir, "mono", "4.5"); - return GDMonoMarshal::mono_string_from_godot(framework_path); - } - - ERR_EXPLAIN("Cannot find Mono's assemblies directory in the registry"); - ERR_FAIL_V(NULL); -#else - return NULL; -#endif -} - MonoString *godot_icall_BuildInstance_get_MonoWindowsBinDir() { #if defined(WINDOWS_ENABLED) @@ -216,7 +203,6 @@ void GodotSharpBuilds::register_internal_calls() { mono_add_internal_call("GodotSharpTools.Build.BuildSystem::godot_icall_BuildInstance_ExitCallback", (void *)godot_icall_BuildInstance_ExitCallback); mono_add_internal_call("GodotSharpTools.Build.BuildInstance::godot_icall_BuildInstance_get_MSBuildPath", (void *)godot_icall_BuildInstance_get_MSBuildPath); - mono_add_internal_call("GodotSharpTools.Build.BuildInstance::godot_icall_BuildInstance_get_FrameworkPath", (void *)godot_icall_BuildInstance_get_FrameworkPath); mono_add_internal_call("GodotSharpTools.Build.BuildInstance::godot_icall_BuildInstance_get_MonoWindowsBinDir", (void *)godot_icall_BuildInstance_get_MonoWindowsBinDir); mono_add_internal_call("GodotSharpTools.Build.BuildInstance::godot_icall_BuildInstance_get_UsingMonoMSBuildOnWindows", (void *)godot_icall_BuildInstance_get_UsingMonoMSBuildOnWindows); } @@ -459,7 +445,11 @@ GodotSharpBuilds::GodotSharpBuilds() { // Build tool settings EditorSettings *ed_settings = EditorSettings::get_singleton(); +#ifdef WINDOWS_ENABLED + EDITOR_DEF("mono/builds/build_tool", MSBUILD_VS); +#else EDITOR_DEF("mono/builds/build_tool", MSBUILD_MONO); +#endif ed_settings->add_property_hint(PropertyInfo(Variant::INT, "mono/builds/build_tool", PROPERTY_HINT_ENUM, PROP_NAME_MSBUILD_MONO diff --git a/modules/mono/editor/godotsharp_editor.cpp b/modules/mono/editor/godotsharp_editor.cpp index ee93229700..17e29fba19 100644 --- a/modules/mono/editor/godotsharp_editor.cpp +++ b/modules/mono/editor/godotsharp_editor.cpp @@ -272,19 +272,50 @@ Error GodotSharpEditor::open_in_external_editor(const Ref<Script> &p_script, int static String vscode_path; if (vscode_path.empty() || !FileAccess::exists(vscode_path)) { - static List<String> vscode_name; - vscode_name.push_back("code"); - vscode_name.push_back("code-oss"); - vscode_name.push_back("vscode"); - vscode_name.push_back("vscode-oss"); - vscode_name.push_back("visual-studio-code"); - vscode_name.push_back("visual-studio-code-oss"); // Try to search it again if it wasn't found last time or if it was removed from its location - for (int i = 0; i < vscode_name.size(); i++) { - vscode_path = path_which(vscode_name[i]); - if (!vscode_path.empty() || FileAccess::exists(vscode_path)) + bool found = false; + + // TODO: Use initializer lists once C++11 is allowed + + // Try with hint paths + static Vector<String> hint_paths; +#ifdef WINDOWS_ENABLED + if (hint_paths.empty()) { + hint_paths.push_back(OS::get_singleton()->get_environment("ProgramFiles") + "\\Microsoft VS Code\\Code.exe"); + if (sizeof(size_t) == 8) { + hint_paths.push_back(OS::get_singleton()->get_environment("ProgramFiles(x86)") + "\\Microsoft VS Code\\Code.exe"); + } + } +#endif + for (int i = 0; i < hint_paths.size(); i++) { + vscode_path = hint_paths[i]; + if (FileAccess::exists(vscode_path)) { + found = true; break; + } + } + + if (!found) { + static Vector<String> vscode_names; + if (vscode_names.empty()) { + vscode_names.push_back("code"); + vscode_names.push_back("code-oss"); + vscode_names.push_back("vscode"); + vscode_names.push_back("vscode-oss"); + vscode_names.push_back("visual-studio-code"); + vscode_names.push_back("visual-studio-code-oss"); + } + for (int i = 0; i < vscode_names.size(); i++) { + vscode_path = path_which(vscode_names[i]); + if (!vscode_path.empty()) { + found = true; + break; + } + } } + + if (!found) + vscode_path.clear(); // Not found, clear so next time the empty() check is enough } List<String> args; diff --git a/modules/mono/editor/godotsharp_export.cpp b/modules/mono/editor/godotsharp_export.cpp index 47341e3555..ee5fed1a0c 100644 --- a/modules/mono/editor/godotsharp_export.cpp +++ b/modules/mono/editor/godotsharp_export.cpp @@ -124,7 +124,7 @@ void GodotSharpExport::_export_begin(const Set<String> &p_features, bool p_debug ERR_FAIL_COND(!load_success); Vector<String> search_dirs; - GDMonoAssembly::fill_search_dirs(search_dirs); + GDMonoAssembly::fill_search_dirs(search_dirs, build_config); Error depend_error = _get_assembly_dependencies(scripts_assembly, search_dirs, dependencies); ERR_FAIL_COND(depend_error != OK); } @@ -194,8 +194,8 @@ Error GodotSharpExport::_get_assembly_dependencies(GDMonoAssembly *p_assembly, c String path; bool has_extension = ref_name.ends_with(".dll") || ref_name.ends_with(".exe"); - for (int i = 0; i < p_search_dirs.size(); i++) { - const String &search_dir = p_search_dirs[i]; + for (int j = 0; j < p_search_dirs.size(); j++) { + const String &search_dir = p_search_dirs[j]; if (has_extension) { path = search_dir.plus_file(ref_name); diff --git a/modules/mono/editor/mono_bottom_panel.cpp b/modules/mono/editor/mono_bottom_panel.cpp index d3efa288e9..cc9822e319 100644 --- a/modules/mono/editor/mono_bottom_panel.cpp +++ b/modules/mono/editor/mono_bottom_panel.cpp @@ -156,10 +156,20 @@ void MonoBottomPanel::_build_project_pressed() { if (!FileAccess::exists(GodotSharpDirs::get_project_sln_path())) return; // No solution to build - String scripts_metadata_path = GodotSharpDirs::get_res_metadata_dir().plus_file("scripts_metadata.editor"); - Error metadata_err = CSharpProject::generate_scripts_metadata(GodotSharpDirs::get_project_csproj_path(), scripts_metadata_path); + String scripts_metadata_path_editor = GodotSharpDirs::get_res_metadata_dir().plus_file("scripts_metadata.editor"); + String scripts_metadata_path_player = GodotSharpDirs::get_res_metadata_dir().plus_file("scripts_metadata.editor_player"); + + Error metadata_err = CSharpProject::generate_scripts_metadata(GodotSharpDirs::get_project_csproj_path(), scripts_metadata_path_editor); ERR_FAIL_COND(metadata_err != OK); + if (FileAccess::exists(scripts_metadata_path_editor)) { + DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES); + Error copy_err = da->copy(scripts_metadata_path_editor, scripts_metadata_path_player); + + ERR_EXPLAIN("Failed to copy scripts metadata file"); + ERR_FAIL_COND(copy_err != OK); + } + bool build_success = GodotSharpBuilds::get_singleton()->build_project_blocking("Tools"); if (build_success) { diff --git a/modules/mono/editor/script_class_parser.cpp b/modules/mono/editor/script_class_parser.cpp index 1281ed669f..53a043b675 100644 --- a/modules/mono/editor/script_class_parser.cpp +++ b/modules/mono/editor/script_class_parser.cpp @@ -346,7 +346,7 @@ Error ScriptClassParser::_parse_class_base(Vector<String> &r_base) { bool generic = false; if (tk == TK_OP_LESS) { - Error err = _skip_generic_type_params(); + err = _skip_generic_type_params(); if (err) return err; // We don't add it to the base list if it's generic @@ -355,11 +355,11 @@ Error ScriptClassParser::_parse_class_base(Vector<String> &r_base) { } if (tk == TK_COMMA) { - Error err = _parse_class_base(r_base); + err = _parse_class_base(r_base); if (err) return err; } else if (tk == TK_IDENTIFIER && String(value) == "where") { - Error err = _parse_type_constraints(); + err = _parse_type_constraints(); if (err) { return err; } diff --git a/modules/mono/glue/Managed/Files/Array.cs b/modules/mono/glue/Managed/Files/Array.cs index d5a35d7ae0..9c804eba64 100644 --- a/modules/mono/glue/Managed/Files/Array.cs +++ b/modules/mono/glue/Managed/Files/Array.cs @@ -50,6 +50,9 @@ namespace Godot.Collections internal IntPtr GetPtr() { + if (disposed) + throw new ObjectDisposedException(GetType().FullName); + return safeHandle.DangerousGetHandle(); } diff --git a/modules/mono/glue/Managed/Files/Dictionary.cs b/modules/mono/glue/Managed/Files/Dictionary.cs index 7695f03cd6..fb4521065f 100644 --- a/modules/mono/glue/Managed/Files/Dictionary.cs +++ b/modules/mono/glue/Managed/Files/Dictionary.cs @@ -54,6 +54,9 @@ namespace Godot.Collections internal IntPtr GetPtr() { + if (disposed) + throw new ObjectDisposedException(GetType().FullName); + return safeHandle.DangerousGetHandle(); } diff --git a/modules/mono/glue/Managed/Files/GD.cs b/modules/mono/glue/Managed/Files/GD.cs index 75a35a9eea..3afaf5d08b 100644 --- a/modules/mono/glue/Managed/Files/GD.cs +++ b/modules/mono/glue/Managed/Files/GD.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Runtime.CompilerServices; #if REAL_T_IS_DOUBLE using real_t = System.Double; @@ -50,7 +51,7 @@ namespace Godot return godot_icall_GD_hash(var); } - public static Object InstanceFromId(int instanceId) + public static Object InstanceFromId(ulong instanceId) { return godot_icall_GD_instance_from_id(instanceId); } @@ -110,71 +111,62 @@ namespace Godot godot_icall_GD_printt(what); } - public static int[] Range(int length) + public static double Randf() { - var ret = new int[length]; - - for (int i = 0; i < length; i++) - { - ret[i] = i; - } - - return ret; + return godot_icall_GD_randf(); } - public static int[] Range(int from, int to) + public static uint Randi() { - if (to < from) - return new int[0]; + return godot_icall_GD_randi(); + } - var ret = new int[to - from]; + public static void Randomize() + { + godot_icall_GD_randomize(); + } - for (int i = from; i < to; i++) - { - ret[i - from] = i; - } + public static double RandRange(double from, double to) + { + return godot_icall_GD_rand_range(from, to); + } - return ret; + public static uint RandSeed(ulong seed, out ulong newSeed) + { + return godot_icall_GD_rand_seed(seed, out newSeed); } - public static int[] Range(int from, int to, int increment) + public static IEnumerable<int> Range(int end) { - if (to < from && increment > 0) - return new int[0]; - if (to > from && increment < 0) - return new int[0]; + return Range(0, end, 1); + } - // Calculate count - int count; + public static IEnumerable<int> Range(int start, int end) + { + return Range(start, end, 1); + } - if (increment > 0) - count = (to - from - 1) / increment + 1; - else - count = (from - to - 1) / -increment + 1; + public static IEnumerable<int> Range(int start, int end, int step) + { + if (end < start && step > 0) + yield break; - var ret = new int[count]; + if (end > start && step < 0) + yield break; - if (increment > 0) + if (step > 0) { - int idx = 0; - for (int i = from; i < to; i += increment) - { - ret[idx++] = i; - } + for (int i = start; i < end; i += step) + yield return i; } else { - int idx = 0; - for (int i = from; i > to; i += increment) - { - ret[idx++] = i; - } + for (int i = start; i > end; i += step) + yield return i; } - - return ret; } - public static void Seed(int seed) + public static void Seed(ulong seed) { godot_icall_GD_seed(seed); } @@ -214,7 +206,7 @@ namespace Godot internal extern static int godot_icall_GD_hash(object var); [MethodImpl(MethodImplOptions.InternalCall)] - internal extern static Object godot_icall_GD_instance_from_id(int instance_id); + internal extern static Object godot_icall_GD_instance_from_id(ulong instance_id); [MethodImpl(MethodImplOptions.InternalCall)] internal extern static void godot_icall_GD_print(object[] what); @@ -232,7 +224,22 @@ namespace Godot internal extern static void godot_icall_GD_printt(object[] what); [MethodImpl(MethodImplOptions.InternalCall)] - internal extern static void godot_icall_GD_seed(int seed); + internal extern static double godot_icall_GD_randf(); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static uint godot_icall_GD_randi(); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static void godot_icall_GD_randomize(); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static double godot_icall_GD_rand_range(double from, double to); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static uint godot_icall_GD_rand_seed(ulong seed, out ulong newSeed); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static void godot_icall_GD_seed(ulong seed); [MethodImpl(MethodImplOptions.InternalCall)] internal extern static string godot_icall_GD_str(object[] what); diff --git a/modules/mono/glue/Managed/Files/NodePath.cs b/modules/mono/glue/Managed/Files/NodePath.cs index 2c89bec87f..94a4ed1de9 100644 --- a/modules/mono/glue/Managed/Files/NodePath.cs +++ b/modules/mono/glue/Managed/Files/NodePath.cs @@ -3,7 +3,7 @@ using System.Runtime.CompilerServices; namespace Godot { - public partial class NodePath : IDisposable + public sealed partial class NodePath : IDisposable { private bool disposed = false; @@ -11,7 +11,13 @@ namespace Godot internal static IntPtr GetPtr(NodePath instance) { - return instance == null ? IntPtr.Zero : instance.ptr; + if (instance == null) + return IntPtr.Zero; + + if (instance.disposed) + throw new ObjectDisposedException(instance.GetType().FullName); + + return instance.ptr; } ~NodePath() @@ -25,7 +31,7 @@ namespace Godot GC.SuppressFinalize(this); } - protected virtual void Dispose(bool disposing) + private void Dispose(bool disposing) { if (disposed) return; @@ -49,7 +55,7 @@ namespace Godot get { return ptr; } } - public NodePath() : this(string.Empty) {} + public NodePath() : this(string.Empty) { } public NodePath(string path) { diff --git a/modules/mono/glue/Managed/Files/Object.base.cs b/modules/mono/glue/Managed/Files/Object.base.cs index 30490a715f..41fc43996f 100644 --- a/modules/mono/glue/Managed/Files/Object.base.cs +++ b/modules/mono/glue/Managed/Files/Object.base.cs @@ -30,7 +30,13 @@ namespace Godot internal static IntPtr GetPtr(Object instance) { - return instance == null ? IntPtr.Zero : instance.ptr; + if (instance == null) + return IntPtr.Zero; + + if (instance.disposed) + throw new ObjectDisposedException(instance.GetType().FullName); + + return instance.ptr; } ~Object() diff --git a/modules/mono/glue/Managed/Files/Quat.cs b/modules/mono/glue/Managed/Files/Quat.cs index fd1ac01083..d4dcff583a 100644 --- a/modules/mono/glue/Managed/Files/Quat.cs +++ b/modules/mono/glue/Managed/Files/Quat.cs @@ -347,9 +347,9 @@ namespace Godot public override bool Equals(object obj) { - if (obj is Vector2) + if (obj is Quat) { - return Equals((Vector2)obj); + return Equals((Quat)obj); } return false; diff --git a/modules/mono/glue/Managed/Files/RID.cs b/modules/mono/glue/Managed/Files/RID.cs index b862b8cac0..f1268c8518 100644 --- a/modules/mono/glue/Managed/Files/RID.cs +++ b/modules/mono/glue/Managed/Files/RID.cs @@ -3,7 +3,7 @@ using System.Runtime.CompilerServices; namespace Godot { - public partial class RID : IDisposable + public sealed partial class RID : IDisposable { private bool disposed = false; @@ -11,7 +11,13 @@ namespace Godot internal static IntPtr GetPtr(RID instance) { - return instance == null ? IntPtr.Zero : instance.ptr; + if (instance == null) + return IntPtr.Zero; + + if (instance.disposed) + throw new ObjectDisposedException(instance.GetType().FullName); + + return instance.ptr; } ~RID() @@ -25,7 +31,7 @@ namespace Godot GC.SuppressFinalize(this); } - protected virtual void Dispose(bool disposing) + private void Dispose(bool disposing) { if (disposed) return; diff --git a/modules/mono/glue/Managed/Files/Transform2D.cs b/modules/mono/glue/Managed/Files/Transform2D.cs index c9e5b560b2..53c8abf08b 100644 --- a/modules/mono/glue/Managed/Files/Transform2D.cs +++ b/modules/mono/glue/Managed/Files/Transform2D.cs @@ -13,21 +13,44 @@ namespace Godot { public Vector2 x; public Vector2 y; - public Vector2 o; - - public Vector2 Origin - { - get { return o; } - } + public Vector2 origin; public real_t Rotation { - get { return Mathf.Atan2(y.x, o.y); } + get + { + real_t det = BasisDeterminant(); + Transform2D t = Orthonormalized(); + if (det < 0) + { + t.ScaleBasis(new Vector2(1, -1)); + } + return Mathf.Atan2(t.x.y, t.x.x); + } + set + { + Vector2 scale = Scale; + x.x = y.y = Mathf.Cos(value); + x.y = y.x = Mathf.Sin(value); + y.x *= -1; + Scale = scale; + } } public Vector2 Scale { - get { return new Vector2(x.Length(), y.Length()); } + get + { + real_t detSign = Mathf.Sign(BasisDeterminant()); + return new Vector2(x.Length(), detSign * y.Length()); + } + set + { + x = x.Normalized(); + y = y.Normalized(); + x *= value.x; + y *= value.y; + } } public Vector2 this[int index] @@ -41,7 +64,7 @@ namespace Godot case 1: return y; case 2: - return o; + return origin; default: throw new IndexOutOfRangeException(); } @@ -57,7 +80,7 @@ namespace Godot y = value; return; case 2: - o = value; + origin = value; return; default: throw new IndexOutOfRangeException(); @@ -65,7 +88,6 @@ namespace Godot } } - public real_t this[int index, int axis] { get @@ -100,32 +122,37 @@ namespace Godot { var inv = this; - real_t det = this[0, 0] * this[1, 1] - this[1, 0] * this[0, 1]; + real_t det = BasisDeterminant(); if (det == 0) { return new Transform2D ( - float.NaN, float.NaN, - float.NaN, float.NaN, - float.NaN, float.NaN + real_t.NaN, real_t.NaN, + real_t.NaN, real_t.NaN, + real_t.NaN, real_t.NaN ); } - real_t idet = 1.0f / det; + real_t detInv = 1.0f / det; real_t temp = this[0, 0]; this[0, 0] = this[1, 1]; this[1, 1] = temp; - this[0] *= new Vector2(idet, -idet); - this[1] *= new Vector2(-idet, idet); + this[0] *= new Vector2(detInv, -detInv); + this[1] *= new Vector2(-detInv, detInv); this[2] = BasisXform(-this[2]); return inv; } + private real_t BasisDeterminant() + { + return x.x * y.y - x.y * y.x; + } + public Vector2 BasisXform(Vector2 v) { return new Vector2(Tdotx(v), Tdoty(v)); @@ -168,8 +195,8 @@ namespace Godot } // Extract parameters - Vector2 p1 = Origin; - Vector2 p2 = m.Origin; + Vector2 p1 = origin; + Vector2 p2 = m.origin; // Construct matrix var res = new Transform2D(Mathf.Atan2(v.y, v.x), p1.LinearInterpolate(p2, c)); @@ -189,7 +216,7 @@ namespace Godot inv.x.y = inv.y.x; inv.y.x = temp; - inv.o = inv.BasisXform(-inv.o); + inv.origin = inv.BasisXform(-inv.origin); return inv; } @@ -221,10 +248,18 @@ namespace Godot var copy = this; copy.x *= scale; copy.y *= scale; - copy.o *= scale; + copy.origin *= scale; return copy; } + private void ScaleBasis(Vector2 scale) + { + x.x *= scale.x; + x.y *= scale.y; + y.x *= scale.x; + y.y *= scale.y; + } + private real_t Tdotx(Vector2 with) { return this[0, 0] * with[0] + this[1, 0] * with[1]; @@ -238,59 +273,56 @@ namespace Godot public Transform2D Translated(Vector2 offset) { var copy = this; - copy.o += copy.BasisXform(offset); + copy.origin += copy.BasisXform(offset); return copy; } public Vector2 Xform(Vector2 v) { - return new Vector2(Tdotx(v), Tdoty(v)) + o; + return new Vector2(Tdotx(v), Tdoty(v)) + origin; } public Vector2 XformInv(Vector2 v) { - Vector2 vInv = v - o; + Vector2 vInv = v - origin; return new Vector2(x.Dot(vInv), y.Dot(vInv)); } // Constants - private static readonly Transform2D _identity = new Transform2D(new Vector2(1f, 0f), new Vector2(0f, 1f), Vector2.Zero); - private static readonly Transform2D _flipX = new Transform2D(new Vector2(-1f, 0f), new Vector2(0f, 1f), Vector2.Zero); - private static readonly Transform2D _flipY = new Transform2D(new Vector2(1f, 0f), new Vector2(0f, -1f), Vector2.Zero); + private static readonly Transform2D _identity = new Transform2D(1, 0, 0, 1, 0, 0); + private static readonly Transform2D _flipX = new Transform2D(-1, 0, 0, 1, 0, 0); + private static readonly Transform2D _flipY = new Transform2D(1, 0, 0, -1, 0, 0); public static Transform2D Identity { get { return _identity; } } public static Transform2D FlipX { get { return _flipX; } } public static Transform2D FlipY { get { return _flipY; } } // Constructors - public Transform2D(Vector2 xAxis, Vector2 yAxis, Vector2 origin) + public Transform2D(Vector2 xAxis, Vector2 yAxis, Vector2 originPos) { x = xAxis; y = yAxis; - o = origin; + origin = originPos; } public Transform2D(real_t xx, real_t xy, real_t yx, real_t yy, real_t ox, real_t oy) { x = new Vector2(xx, xy); y = new Vector2(yx, yy); - o = new Vector2(ox, oy); + origin = new Vector2(ox, oy); } public Transform2D(real_t rot, Vector2 pos) { - real_t cr = Mathf.Cos(rot); - real_t sr = Mathf.Sin(rot); - x.x = cr; - y.y = cr; - x.y = -sr; - y.x = sr; - o = pos; + x.x = y.y = Mathf.Cos(rot); + x.y = y.x = Mathf.Sin(rot); + y.x *= -1; + origin = pos; } public static Transform2D operator *(Transform2D left, Transform2D right) { - left.o = left.Xform(right.o); + left.origin = left.Xform(right.origin); real_t x0, x1, y0, y1; @@ -329,12 +361,12 @@ namespace Godot public bool Equals(Transform2D other) { - return x.Equals(other.x) && y.Equals(other.y) && o.Equals(other.o); + return x.Equals(other.x) && y.Equals(other.y) && origin.Equals(other.origin); } public override int GetHashCode() { - return x.GetHashCode() ^ y.GetHashCode() ^ o.GetHashCode(); + return x.GetHashCode() ^ y.GetHashCode() ^ origin.GetHashCode(); } public override string ToString() @@ -343,7 +375,7 @@ namespace Godot { x.ToString(), y.ToString(), - o.ToString() + origin.ToString() }); } @@ -353,7 +385,7 @@ namespace Godot { x.ToString(format), y.ToString(format), - o.ToString(format) + origin.ToString(format) }); } } diff --git a/modules/mono/glue/base_object_glue.cpp b/modules/mono/glue/base_object_glue.cpp index 2963619b79..fad02b01d3 100644 --- a/modules/mono/glue/base_object_glue.cpp +++ b/modules/mono/glue/base_object_glue.cpp @@ -33,7 +33,7 @@ #ifdef MONO_GLUE_ENABLED #include "core/reference.h" -#include "core/string_db.h" +#include "core/string_name.h" #include "../csharp_script.h" #include "../mono_gd/gd_mono_internals.h" diff --git a/modules/mono/glue/gd_glue.cpp b/modules/mono/glue/gd_glue.cpp index e49ed876e7..5edf49d2bf 100644 --- a/modules/mono/glue/gd_glue.cpp +++ b/modules/mono/glue/gd_glue.cpp @@ -52,7 +52,7 @@ MonoObject *godot_icall_GD_bytes2var(MonoArray *p_bytes) { return GDMonoMarshal::variant_to_mono_object(ret); } -MonoObject *godot_icall_GD_convert(MonoObject *p_what, int p_type) { +MonoObject *godot_icall_GD_convert(MonoObject *p_what, int32_t p_type) { Variant what = GDMonoMarshal::mono_object_to_variant(p_what); const Variant *args[1] = { &what }; Variant::CallError ce; @@ -65,7 +65,7 @@ int godot_icall_GD_hash(MonoObject *p_var) { return GDMonoMarshal::mono_object_to_variant(p_var).hash(); } -MonoObject *godot_icall_GD_instance_from_id(int p_instance_id) { +MonoObject *godot_icall_GD_instance_from_id(uint64_t p_instance_id) { return GDMonoUtils::unmanaged_get_managed(ObjectDB::get_instance(p_instance_id)); } @@ -115,7 +115,29 @@ void godot_icall_GD_printt(MonoArray *p_what) { print_line(str); } -void godot_icall_GD_seed(int p_seed) { +double godot_icall_GD_randf() { + return Math::randf(); +} + +uint32_t godot_icall_GD_randi() { + return Math::rand(); +} + +void godot_icall_GD_randomize() { + Math::randomize(); +} + +double godot_icall_GD_rand_range(double from, double to) { + return Math::random(from, to); +} + +uint32_t godot_icall_GD_rand_seed(uint64_t seed, uint64_t *newSeed) { + int ret = Math::rand_from_seed(&seed); + *newSeed = seed; + return ret; +} + +void godot_icall_GD_seed(uint64_t p_seed) { Math::seed(p_seed); } @@ -201,6 +223,11 @@ void godot_register_gd_icalls() { mono_add_internal_call("Godot.GD::godot_icall_GD_printraw", (void *)godot_icall_GD_printraw); mono_add_internal_call("Godot.GD::godot_icall_GD_prints", (void *)godot_icall_GD_prints); mono_add_internal_call("Godot.GD::godot_icall_GD_printt", (void *)godot_icall_GD_printt); + mono_add_internal_call("Godot.GD::godot_icall_GD_randf", (void *)godot_icall_GD_randf); + mono_add_internal_call("Godot.GD::godot_icall_GD_randi", (void *)godot_icall_GD_randi); + mono_add_internal_call("Godot.GD::godot_icall_GD_randomize", (void *)godot_icall_GD_randomize); + mono_add_internal_call("Godot.GD::godot_icall_GD_rand_range", (void *)godot_icall_GD_rand_range); + mono_add_internal_call("Godot.GD::godot_icall_GD_rand_seed", (void *)godot_icall_GD_rand_seed); mono_add_internal_call("Godot.GD::godot_icall_GD_seed", (void *)godot_icall_GD_seed); mono_add_internal_call("Godot.GD::godot_icall_GD_str", (void *)godot_icall_GD_str); mono_add_internal_call("Godot.GD::godot_icall_GD_str2var", (void *)godot_icall_GD_str2var); diff --git a/modules/mono/glue/gd_glue.h b/modules/mono/glue/gd_glue.h index 00611fef12..ba75d85343 100644 --- a/modules/mono/glue/gd_glue.h +++ b/modules/mono/glue/gd_glue.h @@ -37,11 +37,11 @@ MonoObject *godot_icall_GD_bytes2var(MonoArray *p_bytes); -MonoObject *godot_icall_GD_convert(MonoObject *p_what, int p_type); +MonoObject *godot_icall_GD_convert(MonoObject *p_what, int32_t p_type); int godot_icall_GD_hash(MonoObject *p_var); -MonoObject *godot_icall_GD_instance_from_id(int p_instance_id); +MonoObject *godot_icall_GD_instance_from_id(uint64_t p_instance_id); void godot_icall_GD_print(MonoArray *p_what); @@ -53,7 +53,17 @@ void godot_icall_GD_prints(MonoArray *p_what); void godot_icall_GD_printt(MonoArray *p_what); -void godot_icall_GD_seed(int p_seed); +double godot_icall_GD_randf(); + +uint32_t godot_icall_GD_randi(); + +void godot_icall_GD_randomize(); + +double godot_icall_GD_rand_range(double from, double to); + +uint32_t godot_icall_GD_rand_seed(uint64_t seed, uint64_t *newSeed); + +void godot_icall_GD_seed(uint64_t p_seed); MonoString *godot_icall_GD_str(MonoArray *p_what); diff --git a/modules/mono/godotsharp_dirs.cpp b/modules/mono/godotsharp_dirs.cpp index 3943c0c7d7..09a1fc6fbc 100644 --- a/modules/mono/godotsharp_dirs.cpp +++ b/modules/mono/godotsharp_dirs.cpp @@ -99,7 +99,6 @@ public: String sln_filepath; String csproj_filepath; - String data_mono_bin_dir; String data_editor_tools_dir; String data_editor_prebuilt_api_dir; #endif @@ -107,6 +106,10 @@ public: String data_mono_etc_dir; String data_mono_lib_dir; +#ifdef WINDOWS_ENABLED + String data_mono_bin_dir; +#endif + private: _GodotSharpDirs() { res_data_dir = "res://.mono"; @@ -146,10 +149,13 @@ private: data_editor_prebuilt_api_dir = data_dir_root.plus_file("Api"); String data_mono_root_dir = data_dir_root.plus_file("Mono"); - data_mono_bin_dir = data_mono_root_dir.plus_file("bin"); data_mono_etc_dir = data_mono_root_dir.plus_file("etc"); data_mono_lib_dir = data_mono_root_dir.plus_file("lib"); +#ifdef WINDOWS_ENABLED + data_mono_bin_dir = data_mono_root_dir.plus_file("bin"); +#endif + #ifdef OSX_ENABLED if (!DirAccess::exists(data_editor_tools_dir)) { data_editor_tools_dir = exe_dir.plus_file("../Frameworks/GodotSharp/Tools"); @@ -160,7 +166,6 @@ private: } if (!DirAccess::exists(data_mono_root_dir)) { - data_mono_bin_dir = exe_dir.plus_file("../Frameworks/GodotSharp/Mono/bin"); data_mono_etc_dir = exe_dir.plus_file("../Resources/GodotSharp/Mono/etc"); data_mono_lib_dir = exe_dir.plus_file("../Frameworks/GodotSharp/Mono/lib"); } @@ -178,6 +183,10 @@ private: data_mono_etc_dir = data_mono_root_dir.plus_file("etc"); data_mono_lib_dir = data_mono_root_dir.plus_file("lib"); +#ifdef WINDOWS_ENABLED + data_mono_bin_dir = data_mono_root_dir.plus_file("bin"); +#endif + #ifdef OSX_ENABLED if (!DirAccess::exists(data_mono_root_dir)) { data_mono_etc_dir = exe_dir.plus_file("../Resources/GodotSharp/Mono/etc"); @@ -251,10 +260,6 @@ String get_project_csproj_path() { return _GodotSharpDirs::get_singleton().csproj_filepath; } -String get_data_mono_bin_dir() { - return _GodotSharpDirs::get_singleton().data_mono_bin_dir; -} - String get_data_editor_tools_dir() { return _GodotSharpDirs::get_singleton().data_editor_tools_dir; } @@ -272,4 +277,10 @@ String get_data_mono_lib_dir() { return _GodotSharpDirs::get_singleton().data_mono_lib_dir; } +#ifdef WINDOWS_ENABLED +String get_data_mono_bin_dir() { + return _GodotSharpDirs::get_singleton().data_mono_bin_dir; +} +#endif + } // namespace GodotSharpDirs diff --git a/modules/mono/godotsharp_dirs.h b/modules/mono/godotsharp_dirs.h index a038e6486c..556df959e2 100644 --- a/modules/mono/godotsharp_dirs.h +++ b/modules/mono/godotsharp_dirs.h @@ -53,7 +53,6 @@ String get_build_logs_dir(); String get_project_sln_path(); String get_project_csproj_path(); -String get_data_mono_bin_dir(); String get_data_editor_tools_dir(); String get_data_editor_prebuilt_api_dir(); #endif @@ -61,6 +60,10 @@ String get_data_editor_prebuilt_api_dir(); String get_data_mono_etc_dir(); String get_data_mono_lib_dir(); +#ifdef WINDOWS_ENABLED +String get_data_mono_bin_dir(); +#endif + } // namespace GodotSharpDirs #endif // GODOTSHARP_DIRS_H diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp index ca1ff9f9ff..bba8b1050f 100644 --- a/modules/mono/mono_gd/gd_mono.cpp +++ b/modules/mono/mono_gd/gd_mono.cpp @@ -157,7 +157,17 @@ void GDMono::add_mono_shared_libs_dir_to_path() { path_value += ';'; String bundled_bin_dir = GodotSharpDirs::get_data_mono_bin_dir(); - path_value += DirAccess::exists(bundled_bin_dir) ? bundled_bin_dir : mono_reg_info.bin_dir; +#ifdef TOOLS_ENABLED + if (DirAccess::exists(bundled_bin_dir)) { + path_value += bundled_bin_dir; + } else { + path_value += mono_reg_info.bin_dir; + } +#else + if (DirAccess::exists(bundled_bin_dir)) + path_value += bundled_bin_dir; +#endif // TOOLS_ENABLED + #else path_value += ':'; @@ -167,10 +177,10 @@ void GDMono::add_mono_shared_libs_dir_to_path() { } else { // TODO: Do we need to add the lib dir when using the system installed Mono on Unix platforms? } -#endif +#endif // WINDOWS_ENABLED OS::get_singleton()->set_environment(path_var, path_value); -#endif +#endif // WINDOWS_ENABLED || UNIX_ENABLED } void GDMono::initialize() { @@ -231,11 +241,21 @@ void GDMono::initialize() { assembly_rootdir = bundled_assembly_rootdir; config_dir = bundled_config_dir; } + +#ifdef WINDOWS_ENABLED + if (assembly_rootdir.empty() || config_dir.empty()) { + // Assertion: if they are not set, then they weren't found in the registry + CRASH_COND(mono_reg_info.assembly_dir.length() > 0 || mono_reg_info.config_dir.length() > 0); + + ERR_PRINT("Cannot find Mono in the registry"); + } +#endif // WINDOWS_ENABLED + #else // These are always the directories in export templates assembly_rootdir = bundled_assembly_rootdir; config_dir = bundled_config_dir; -#endif +#endif // TOOLS_ENABLED // Leak if we call mono_set_dirs more than once mono_set_dirs(assembly_rootdir.length() ? assembly_rootdir.utf8().get_data() : NULL, @@ -253,6 +273,29 @@ void GDMono::initialize() { mono_install_unhandled_exception_hook(&unhandled_exception_hook, NULL); +#ifdef TOOLS_ENABLED + if (!DirAccess::exists("res://.mono")) { + // 'res://.mono/' is missing so there is nothing to load. We don't need to initialize mono, but + // we still do so unless mscorlib is missing (which is the case for projects that don't use C#). + + String mscorlib_fname("mscorlib.dll"); + + Vector<String> search_dirs; + GDMonoAssembly::fill_search_dirs(search_dirs); + + bool found = false; + for (int i = 0; i < search_dirs.size(); i++) { + if (FileAccess::exists(search_dirs[i].plus_file(mscorlib_fname))) { + found = true; + break; + } + } + + if (!found) + return; // mscorlib is missing, do not initialize mono + } +#endif + root_domain = mono_jit_init_version("GodotEngine.RootDomain", "v4.0.30319"); ERR_EXPLAIN("Mono: Failed to initialize runtime"); diff --git a/modules/mono/mono_gd/gd_mono_class.cpp b/modules/mono/mono_gd/gd_mono_class.cpp index bf2a84c708..92324d73f9 100644 --- a/modules/mono/mono_gd/gd_mono_class.cpp +++ b/modules/mono/mono_gd/gd_mono_class.cpp @@ -59,8 +59,16 @@ MonoType *GDMonoClass::get_mono_type() { return get_mono_type(mono_class); } -bool GDMonoClass::is_assignable_from(GDMonoClass *p_from) const { +uint32_t GDMonoClass::get_flags() const { + return mono_class_get_flags(mono_class); +} +bool GDMonoClass::is_static() const { + uint32_t static_class_flags = MONO_TYPE_ATTR_ABSTRACT | MONO_TYPE_ATTR_SEALED; + return (get_flags() & static_class_flags) == static_class_flags; +} + +bool GDMonoClass::is_assignable_from(GDMonoClass *p_from) const { return mono_class_is_assignable_from(mono_class, p_from->mono_class); } diff --git a/modules/mono/mono_gd/gd_mono_class.h b/modules/mono/mono_gd/gd_mono_class.h index 08718ec1a4..4af909450e 100644 --- a/modules/mono/mono_gd/gd_mono_class.h +++ b/modules/mono/mono_gd/gd_mono_class.h @@ -109,6 +109,9 @@ public: String get_full_name() const; MonoType *get_mono_type(); + uint32_t get_flags() const; + bool is_static() const; + bool is_assignable_from(GDMonoClass *p_from) const; _FORCE_INLINE_ StringName get_namespace() const { return namespace_name; } diff --git a/modules/mono/mono_gd/gd_mono_field.h b/modules/mono/mono_gd/gd_mono_field.h index a3244101d8..e348583370 100644 --- a/modules/mono/mono_gd/gd_mono_field.h +++ b/modules/mono/mono_gd/gd_mono_field.h @@ -32,8 +32,8 @@ #define GDMONOFIELD_H #include "gd_mono.h" -#include "gd_mono_class_member.h" #include "gd_mono_header.h" +#include "i_mono_class_member.h" class GDMonoField : public IMonoClassMember { diff --git a/modules/mono/mono_gd/gd_mono_internals.cpp b/modules/mono/mono_gd/gd_mono_internals.cpp index 0daa394e63..c8cba5cf1b 100644 --- a/modules/mono/mono_gd/gd_mono_internals.cpp +++ b/modules/mono/mono_gd/gd_mono_internals.cpp @@ -34,6 +34,8 @@ #include "../mono_gc_handle.h" #include "../utils/macros.h" #include "../utils/thread_local.h" +#include "gd_mono_class.h" +#include "gd_mono_marshal.h" #include "gd_mono_utils.h" #include <mono/metadata/exception.h> @@ -55,10 +57,48 @@ void tie_managed_to_unmanaged(MonoObject *managed, Object *unmanaged) { CRASH_COND(!klass); - Ref<MonoGCHandle> gchandle = ref ? MonoGCHandle::create_weak(managed) : - MonoGCHandle::create_strong(managed); + GDMonoClass *native = GDMonoUtils::get_class_native_base(klass); - Ref<CSharpScript> script = CSharpScript::create_for_managed_type(klass); + CRASH_COND(native == NULL); + + if (native == klass) { + // If it's just a wrapper Godot class and not a custom inheriting class, then attach a + // script binding instead. One of the advantages of this is that if a script is attached + // later and it's not a C# script, then the managed object won't have to be disposed. + // Another reason for doing this is that this instance could outlive CSharpLanguage, which would + // be problematic when using a script. See: https://github.com/godotengine/godot/issues/25621 + + CSharpScriptBinding script_binding; + + script_binding.inited = true; + script_binding.type_name = NATIVE_GDMONOCLASS_NAME(klass); + script_binding.wrapper_class = klass; + script_binding.gchandle = MonoGCHandle::create_strong(managed); + + Reference *kref = Object::cast_to<Reference>(unmanaged); + if (kref) { + // Unsafe refcount increment. The managed instance also counts as a reference. + // This way if the unmanaged world has no references to our owner + // but the managed instance is alive, the refcount will be 1 instead of 0. + // See: godot_icall_Reference_Dtor(MonoObject *p_obj, Object *p_ptr) + + kref->reference(); + } + + // The object was just created, no script instance binding should have been attached + CRASH_COND(unmanaged->has_script_instance_binding(CSharpLanguage::get_singleton()->get_language_index())); + + void *data = (void *)CSharpLanguage::get_singleton()->insert_script_binding(unmanaged, script_binding); + + // Should be thread safe because the object was just created and nothing else should be referencing it + unmanaged->set_script_instance_binding(CSharpLanguage::get_singleton()->get_language_index(), data); + + return; + } + + Ref<MonoGCHandle> gchandle = ref ? MonoGCHandle::create_weak(managed) : MonoGCHandle::create_strong(managed); + + Ref<CSharpScript> script = CSharpScript::create_for_managed_type(klass, native); CRASH_COND(script.is_null()); diff --git a/modules/mono/mono_gd/gd_mono_marshal.cpp b/modules/mono/mono_gd/gd_mono_marshal.cpp index 74395de41c..7fe8ae608a 100644 --- a/modules/mono/mono_gd/gd_mono_marshal.cpp +++ b/modules/mono/mono_gd/gd_mono_marshal.cpp @@ -68,39 +68,39 @@ Variant::Type managed_to_variant_type(const ManagedType &p_type) { } break; case MONO_TYPE_VALUETYPE: { - GDMonoClass *tclass = p_type.type_class; + GDMonoClass *vtclass = p_type.type_class; - if (tclass == CACHED_CLASS(Vector2)) + if (vtclass == CACHED_CLASS(Vector2)) return Variant::VECTOR2; - if (tclass == CACHED_CLASS(Rect2)) + if (vtclass == CACHED_CLASS(Rect2)) return Variant::RECT2; - if (tclass == CACHED_CLASS(Transform2D)) + if (vtclass == CACHED_CLASS(Transform2D)) return Variant::TRANSFORM2D; - if (tclass == CACHED_CLASS(Vector3)) + if (vtclass == CACHED_CLASS(Vector3)) return Variant::VECTOR3; - if (tclass == CACHED_CLASS(Basis)) + if (vtclass == CACHED_CLASS(Basis)) return Variant::BASIS; - if (tclass == CACHED_CLASS(Quat)) + if (vtclass == CACHED_CLASS(Quat)) return Variant::QUAT; - if (tclass == CACHED_CLASS(Transform)) + if (vtclass == CACHED_CLASS(Transform)) return Variant::TRANSFORM; - if (tclass == CACHED_CLASS(AABB)) + if (vtclass == CACHED_CLASS(AABB)) return Variant::AABB; - if (tclass == CACHED_CLASS(Color)) + if (vtclass == CACHED_CLASS(Color)) return Variant::COLOR; - if (tclass == CACHED_CLASS(Plane)) + if (vtclass == CACHED_CLASS(Plane)) return Variant::PLANE; - if (mono_class_is_enum(tclass->get_mono_ptr())) + if (mono_class_is_enum(vtclass->get_mono_ptr())) return Variant::INT; } break; @@ -294,60 +294,60 @@ MonoObject *variant_to_mono_object(const Variant *p_var, const ManagedType &p_ty } break; case MONO_TYPE_VALUETYPE: { - GDMonoClass *tclass = p_type.type_class; + GDMonoClass *vtclass = p_type.type_class; - if (tclass == CACHED_CLASS(Vector2)) { + if (vtclass == CACHED_CLASS(Vector2)) { GDMonoMarshal::M_Vector2 from = MARSHALLED_OUT(Vector2, p_var->operator ::Vector2()); return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Vector2), &from); } - if (tclass == CACHED_CLASS(Rect2)) { + if (vtclass == CACHED_CLASS(Rect2)) { GDMonoMarshal::M_Rect2 from = MARSHALLED_OUT(Rect2, p_var->operator ::Rect2()); return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Rect2), &from); } - if (tclass == CACHED_CLASS(Transform2D)) { + if (vtclass == CACHED_CLASS(Transform2D)) { GDMonoMarshal::M_Transform2D from = MARSHALLED_OUT(Transform2D, p_var->operator ::Transform2D()); return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Transform2D), &from); } - if (tclass == CACHED_CLASS(Vector3)) { + if (vtclass == CACHED_CLASS(Vector3)) { GDMonoMarshal::M_Vector3 from = MARSHALLED_OUT(Vector3, p_var->operator ::Vector3()); return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Vector3), &from); } - if (tclass == CACHED_CLASS(Basis)) { + if (vtclass == CACHED_CLASS(Basis)) { GDMonoMarshal::M_Basis from = MARSHALLED_OUT(Basis, p_var->operator ::Basis()); return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Basis), &from); } - if (tclass == CACHED_CLASS(Quat)) { + if (vtclass == CACHED_CLASS(Quat)) { GDMonoMarshal::M_Quat from = MARSHALLED_OUT(Quat, p_var->operator ::Quat()); return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Quat), &from); } - if (tclass == CACHED_CLASS(Transform)) { + if (vtclass == CACHED_CLASS(Transform)) { GDMonoMarshal::M_Transform from = MARSHALLED_OUT(Transform, p_var->operator ::Transform()); return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Transform), &from); } - if (tclass == CACHED_CLASS(AABB)) { + if (vtclass == CACHED_CLASS(AABB)) { GDMonoMarshal::M_AABB from = MARSHALLED_OUT(AABB, p_var->operator ::AABB()); return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(AABB), &from); } - if (tclass == CACHED_CLASS(Color)) { + if (vtclass == CACHED_CLASS(Color)) { GDMonoMarshal::M_Color from = MARSHALLED_OUT(Color, p_var->operator ::Color()); return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Color), &from); } - if (tclass == CACHED_CLASS(Plane)) { + if (vtclass == CACHED_CLASS(Plane)) { GDMonoMarshal::M_Plane from = MARSHALLED_OUT(Plane, p_var->operator ::Plane()); return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Plane), &from); } - if (mono_class_is_enum(tclass->get_mono_ptr())) { - MonoType *enum_basetype = mono_class_enum_basetype(tclass->get_mono_ptr()); + if (mono_class_is_enum(vtclass->get_mono_ptr())) { + MonoType *enum_basetype = mono_class_enum_basetype(vtclass->get_mono_ptr()); MonoClass *enum_baseclass = mono_class_from_mono_type(enum_basetype); switch (mono_type_get_type(enum_basetype)) { case MONO_TYPE_BOOLEAN: { @@ -624,39 +624,39 @@ Variant mono_object_to_variant(MonoObject *p_obj) { } break; case MONO_TYPE_VALUETYPE: { - GDMonoClass *tclass = type.type_class; + GDMonoClass *vtclass = type.type_class; - if (tclass == CACHED_CLASS(Vector2)) + if (vtclass == CACHED_CLASS(Vector2)) return MARSHALLED_IN(Vector2, (GDMonoMarshal::M_Vector2 *)mono_object_unbox(p_obj)); - if (tclass == CACHED_CLASS(Rect2)) + if (vtclass == CACHED_CLASS(Rect2)) return MARSHALLED_IN(Rect2, (GDMonoMarshal::M_Rect2 *)mono_object_unbox(p_obj)); - if (tclass == CACHED_CLASS(Transform2D)) + if (vtclass == CACHED_CLASS(Transform2D)) return MARSHALLED_IN(Transform2D, (GDMonoMarshal::M_Transform2D *)mono_object_unbox(p_obj)); - if (tclass == CACHED_CLASS(Vector3)) + if (vtclass == CACHED_CLASS(Vector3)) return MARSHALLED_IN(Vector3, (GDMonoMarshal::M_Vector3 *)mono_object_unbox(p_obj)); - if (tclass == CACHED_CLASS(Basis)) + if (vtclass == CACHED_CLASS(Basis)) return MARSHALLED_IN(Basis, (GDMonoMarshal::M_Basis *)mono_object_unbox(p_obj)); - if (tclass == CACHED_CLASS(Quat)) + if (vtclass == CACHED_CLASS(Quat)) return MARSHALLED_IN(Quat, (GDMonoMarshal::M_Quat *)mono_object_unbox(p_obj)); - if (tclass == CACHED_CLASS(Transform)) + if (vtclass == CACHED_CLASS(Transform)) return MARSHALLED_IN(Transform, (GDMonoMarshal::M_Transform *)mono_object_unbox(p_obj)); - if (tclass == CACHED_CLASS(AABB)) + if (vtclass == CACHED_CLASS(AABB)) return MARSHALLED_IN(AABB, (GDMonoMarshal::M_AABB *)mono_object_unbox(p_obj)); - if (tclass == CACHED_CLASS(Color)) + if (vtclass == CACHED_CLASS(Color)) return MARSHALLED_IN(Color, (GDMonoMarshal::M_Color *)mono_object_unbox(p_obj)); - if (tclass == CACHED_CLASS(Plane)) + if (vtclass == CACHED_CLASS(Plane)) return MARSHALLED_IN(Plane, (GDMonoMarshal::M_Plane *)mono_object_unbox(p_obj)); - if (mono_class_is_enum(tclass->get_mono_ptr())) + if (mono_class_is_enum(vtclass->get_mono_ptr())) return unbox<int32_t>(p_obj); } break; @@ -698,7 +698,11 @@ Variant mono_object_to_variant(MonoObject *p_obj) { // GodotObject if (CACHED_CLASS(GodotObject)->is_assignable_from(type_class)) { Object *ptr = unbox<Object *>(CACHED_FIELD(GodotObject, ptr)->get_value(p_obj)); - return ptr ? Variant(ptr) : Variant(); + if (ptr != NULL) { + Reference *ref = Object::cast_to<Reference>(ptr); + return ref ? Variant(Ref<Reference>(ref)) : Variant(ptr); + } + return Variant(); } if (CACHED_CLASS(NodePath) == type_class) { @@ -736,7 +740,7 @@ Variant mono_object_to_variant(MonoObject *p_obj) { UNLIKELY_UNHANDLED_EXCEPTION(exc); if (is_dict) { - MonoException *exc = NULL; + exc = NULL; MonoObject *ret = type.type_class->get_method("GetPtr")->invoke(p_obj, &exc); UNLIKELY_UNHANDLED_EXCEPTION(exc); return *unbox<Dictionary *>(ret); @@ -749,7 +753,7 @@ Variant mono_object_to_variant(MonoObject *p_obj) { UNLIKELY_UNHANDLED_EXCEPTION(exc); if (is_array) { - MonoException *exc = NULL; + exc = NULL; MonoObject *ret = type.type_class->get_method("GetPtr")->invoke(p_obj, &exc); UNLIKELY_UNHANDLED_EXCEPTION(exc); return *unbox<Array *>(ret); diff --git a/modules/mono/mono_gd/gd_mono_method.h b/modules/mono/mono_gd/gd_mono_method.h index fc035d387c..f74cef438d 100644 --- a/modules/mono/mono_gd/gd_mono_method.h +++ b/modules/mono/mono_gd/gd_mono_method.h @@ -32,8 +32,8 @@ #define GD_MONO_METHOD_H #include "gd_mono.h" -#include "gd_mono_class_member.h" #include "gd_mono_header.h" +#include "i_mono_class_member.h" class GDMonoMethod : public IMonoClassMember { diff --git a/modules/mono/mono_gd/gd_mono_property.h b/modules/mono/mono_gd/gd_mono_property.h index d8a9f69ffb..2700c460b0 100644 --- a/modules/mono/mono_gd/gd_mono_property.h +++ b/modules/mono/mono_gd/gd_mono_property.h @@ -32,8 +32,8 @@ #define GD_MONO_PROPERTY_H #include "gd_mono.h" -#include "gd_mono_class_member.h" #include "gd_mono_header.h" +#include "i_mono_class_member.h" class GDMonoProperty : public IMonoClassMember { diff --git a/modules/mono/mono_gd/gd_mono_utils.cpp b/modules/mono/mono_gd/gd_mono_utils.cpp index ac6ccac3a7..6cc1c8afc2 100644 --- a/modules/mono/mono_gd/gd_mono_utils.cpp +++ b/modules/mono/mono_gd/gd_mono_utils.cpp @@ -39,6 +39,7 @@ #include "../csharp_script.h" #include "../utils/macros.h" +#include "../utils/mutex_utils.h" #include "gd_mono.h" #include "gd_mono_class.h" #include "gd_mono_marshal.h" @@ -281,17 +282,19 @@ MonoObject *unmanaged_get_managed(Object *unmanaged) { void *data = unmanaged->get_script_instance_binding(CSharpLanguage::get_singleton()->get_language_index()); - if (!data) - return NULL; + ERR_FAIL_NULL_V(data, NULL); CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)data)->value(); if (!script_binding.inited) { - // Already had a binding that needs to be setup - CSharpLanguage::get_singleton()->setup_csharp_script_binding(script_binding, unmanaged); + SCOPED_MUTEX_LOCK(CSharpLanguage::get_singleton()->get_language_bind_mutex()); + + if (!script_binding.inited) { // Other thread may have set it up + // Already had a binding that needs to be setup + CSharpLanguage::get_singleton()->setup_csharp_script_binding(script_binding, unmanaged); - if (!script_binding.inited) - return NULL; + ERR_FAIL_COND_V(!script_binding.inited, NULL); + } } Ref<MonoGCHandle> &gchandle = script_binding.gchandle; @@ -371,6 +374,11 @@ GDMonoClass *type_get_proxy_class(const StringName &p_type) { GDMonoClass *klass = GDMono::get_singleton()->get_core_api_assembly()->get_class(BINDINGS_NAMESPACE, class_name); + if (klass && klass->is_static()) { + // A static class means this is a Godot singleton class. If an instance is needed we use Godot.Object. + return mono_cache.class_GodotObject; + } + #ifdef TOOLS_ENABLED if (!klass) { return GDMono::get_singleton()->get_editor_api_assembly()->get_class(BINDINGS_NAMESPACE, class_name); diff --git a/modules/mono/mono_gd/gd_mono_class_member.h b/modules/mono/mono_gd/i_mono_class_member.h index 3058b18c05..553d9edc72 100644 --- a/modules/mono/mono_gd/gd_mono_class_member.h +++ b/modules/mono/mono_gd/i_mono_class_member.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* gd_mono_class_member.h */ +/* i_mono_class_member.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef GD_MONO_CLASS_MEMBER_H -#define GD_MONO_CLASS_MEMBER_H +#ifndef I_MONO_CLASS_MEMBER_H +#define I_MONO_CLASS_MEMBER_H #include "gd_mono_header.h" @@ -65,4 +65,4 @@ public: virtual MonoObject *get_attribute(GDMonoClass *p_attr_class) = 0; }; -#endif // GD_MONO_CLASS_MEMBER_H +#endif // I_MONO_CLASS_MEMBER_H diff --git a/modules/mono/utils/macros.h b/modules/mono/utils/macros.h index 87295a98f2..e44f254e1c 100644 --- a/modules/mono/utils/macros.h +++ b/modules/mono/utils/macros.h @@ -31,10 +31,6 @@ #ifndef UTIL_MACROS_H #define UTIL_MACROS_H -#ifndef __has_cpp_attribute -#define __has_cpp_attribute(attr_token) 0 -#endif - #define _GD_VARNAME_CONCAT_B_(m_ignore, m_name) m_name #define _GD_VARNAME_CONCAT_A_(m_a, m_b, m_c) _GD_VARNAME_CONCAT_B_(hello there, m_a##m_b##m_c) #define _GD_VARNAME_CONCAT_(m_a, m_b, m_c) _GD_VARNAME_CONCAT_A_(m_a, m_b, m_c) @@ -61,7 +57,7 @@ // noreturn // TODO: Get rid of this macro once we upgrade to C++11 -#if __has_cpp_attribute(deprecated) +#if (__cplusplus >= 201103L) #define GD_NORETURN [[noreturn]] #elif defined(__GNUC__) #define GD_NORETURN __attribute__((noreturn)) diff --git a/modules/mono/utils/mono_reg_utils.cpp b/modules/mono/utils/mono_reg_utils.cpp index 76b250e038..0eb4b3b8b3 100644 --- a/modules/mono/utils/mono_reg_utils.cpp +++ b/modules/mono/utils/mono_reg_utils.cpp @@ -158,8 +158,6 @@ MonoRegInfo find_mono() { if (_find_mono_in_reg_old("Software\\Novell\\Mono", info) == ERROR_SUCCESS) return info; - ERR_PRINT("Cannot find mono in the registry"); - return MonoRegInfo(); } diff --git a/modules/recast/navigation_mesh_generator.cpp b/modules/recast/navigation_mesh_generator.cpp index 29f5e4c363..80e98a13a5 100644 --- a/modules/recast/navigation_mesh_generator.cpp +++ b/modules/recast/navigation_mesh_generator.cpp @@ -66,26 +66,26 @@ void NavigationMeshGenerator::_add_mesh(const Ref<Mesh> &p_mesh, const Transform PoolVector<int> mesh_indices = a[Mesh::ARRAY_INDEX]; PoolVector<int>::Read ir = mesh_indices.read(); - for (int i = 0; i < mesh_vertices.size(); i++) { - _add_vertex(p_xform.xform(vr[i]), p_verticies); + for (int j = 0; j < mesh_vertices.size(); j++) { + _add_vertex(p_xform.xform(vr[j]), p_verticies); } - for (int i = 0; i < face_count; i++) { + for (int j = 0; j < face_count; j++) { // CCW - p_indices.push_back(current_vertex_count + (ir[i * 3 + 0])); - p_indices.push_back(current_vertex_count + (ir[i * 3 + 2])); - p_indices.push_back(current_vertex_count + (ir[i * 3 + 1])); + p_indices.push_back(current_vertex_count + (ir[j * 3 + 0])); + p_indices.push_back(current_vertex_count + (ir[j * 3 + 2])); + p_indices.push_back(current_vertex_count + (ir[j * 3 + 1])); } } else { face_count = mesh_vertices.size() / 3; - for (int i = 0; i < face_count; i++) { - _add_vertex(p_xform.xform(vr[i * 3 + 0]), p_verticies); - _add_vertex(p_xform.xform(vr[i * 3 + 2]), p_verticies); - _add_vertex(p_xform.xform(vr[i * 3 + 1]), p_verticies); - - p_indices.push_back(current_vertex_count + (i * 3 + 0)); - p_indices.push_back(current_vertex_count + (i * 3 + 1)); - p_indices.push_back(current_vertex_count + (i * 3 + 2)); + for (int j = 0; j < face_count; j++) { + _add_vertex(p_xform.xform(vr[j * 3 + 0]), p_verticies); + _add_vertex(p_xform.xform(vr[j * 3 + 2]), p_verticies); + _add_vertex(p_xform.xform(vr[j * 3 + 1]), p_verticies); + + p_indices.push_back(current_vertex_count + (j * 3 + 0)); + p_indices.push_back(current_vertex_count + (j * 3 + 1)); + p_indices.push_back(current_vertex_count + (j * 3 + 2)); } } } diff --git a/modules/stb_vorbis/resource_importer_ogg_vorbis.h b/modules/stb_vorbis/resource_importer_ogg_vorbis.h index ca2d662e61..f61fc91cda 100644 --- a/modules/stb_vorbis/resource_importer_ogg_vorbis.h +++ b/modules/stb_vorbis/resource_importer_ogg_vorbis.h @@ -32,7 +32,7 @@ #define RESOURCEIMPORTEROGGVORBIS_H #include "audio_stream_ogg_vorbis.h" -#include "core/io/resource_import.h" +#include "core/io/resource_importer.h" class ResourceImporterOGGVorbis : public ResourceImporter { GDCLASS(ResourceImporterOGGVorbis, ResourceImporter) diff --git a/modules/theora/video_stream_theora.cpp b/modules/theora/video_stream_theora.cpp index 31723c5c76..14c5ddd7f2 100644 --- a/modules/theora/video_stream_theora.cpp +++ b/modules/theora/video_stream_theora.cpp @@ -296,8 +296,8 @@ void VideoStreamPlaybackTheora::set_file(const String &p_file) { if (ogg_sync_pageout(&oy, &og) > 0) { queue_page(&og); /* demux into the appropriate stream */ } else { - int ret = buffer_data(); /* someone needs more data */ - if (ret == 0) { + int ret2 = buffer_data(); /* someone needs more data */ + if (ret2 == 0) { fprintf(stderr, "End of file while searching for codec headers.\n"); clear(); return; diff --git a/modules/upnp/register_types.cpp b/modules/upnp/register_types.cpp index abb73a3605..fbf0ee8b97 100644 --- a/modules/upnp/register_types.cpp +++ b/modules/upnp/register_types.cpp @@ -33,7 +33,7 @@ #include "core/error_macros.h" #include "upnp.h" -#include "upnpdevice.h" +#include "upnp_device.h" void register_upnp_types() { diff --git a/modules/upnp/upnp.h b/modules/upnp/upnp.h index b73908724d..011b6d44b3 100644 --- a/modules/upnp/upnp.h +++ b/modules/upnp/upnp.h @@ -33,7 +33,7 @@ #include "core/reference.h" -#include "upnpdevice.h" +#include "upnp_device.h" #include <miniupnpc/miniupnpc.h> diff --git a/modules/upnp/upnpdevice.cpp b/modules/upnp/upnp_device.cpp index 2fb2102df9..4d67e3ddc8 100644 --- a/modules/upnp/upnpdevice.cpp +++ b/modules/upnp/upnp_device.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* upnpdevice.cpp */ +/* upnp_device.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,7 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "upnpdevice.h" +#include "upnp_device.h" #include "upnp.h" diff --git a/modules/upnp/upnpdevice.h b/modules/upnp/upnp_device.h index 20fe5c62fe..09fce6af89 100644 --- a/modules/upnp/upnpdevice.h +++ b/modules/upnp/upnp_device.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* upnpdevice.h */ +/* upnp_device.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef GODOT_UPNPDEVICE_H -#define GODOT_UPNPDEVICE_H +#ifndef GODOT_UPNP_DEVICE_H +#define GODOT_UPNP_DEVICE_H #include "core/reference.h" @@ -92,4 +92,4 @@ private: VARIANT_ENUM_CAST(UPNPDevice::IGDStatus) -#endif // GODOT_UPNPDEVICE_H +#endif // GODOT_UPNP_DEVICE_H diff --git a/modules/visual_script/doc_classes/VisualScriptCondition.xml b/modules/visual_script/doc_classes/VisualScriptCondition.xml index 4657436c8f..a7b1028c0c 100644 --- a/modules/visual_script/doc_classes/VisualScriptCondition.xml +++ b/modules/visual_script/doc_classes/VisualScriptCondition.xml @@ -4,7 +4,7 @@ A Visual Script node which branches the flow. </brief_description> <description> - A Visual Script node that checks a [bool] input port. If [code]true[/code], it will exit via the “true†sequence port. If [code]false[/code], it will exit via the "false" sequence port. After exiting either, it exits via the “done†port. Sequence ports may be left disconnected. + A Visual Script node that checks a [bool] input port. If [code]true[/code], it will exit via the "true" sequence port. If [code]false[/code], it will exit via the "false" sequence port. After exiting either, it exits via the "done" port. Sequence ports may be left disconnected. [b]Input Ports:[/b] - Sequence: [code]if (cond) is[/code] - Data (boolean): [code]cond[/code] diff --git a/modules/visual_script/visual_script.cpp b/modules/visual_script/visual_script.cpp index 0027300e9f..2c89e5a35c 100644 --- a/modules/visual_script/visual_script.cpp +++ b/modules/visual_script/visual_script.cpp @@ -1165,9 +1165,9 @@ void VisualScript::_set_data(const Dictionary &p_data) { Array nodes = func["nodes"]; - for (int i = 0; i < nodes.size(); i += 3) { + for (int j = 0; j < nodes.size(); j += 3) { - add_node(name, nodes[i], nodes[i + 2], nodes[i + 1]); + add_node(name, nodes[j], nodes[j + 2], nodes[j + 1]); } Array sequence_connections = func["sequence_connections"]; diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/visual_script_editor.cpp index 040d61a31e..7e54891d97 100644 --- a/modules/visual_script/visual_script_editor.cpp +++ b/modules/visual_script/visual_script_editor.cpp @@ -3103,7 +3103,7 @@ void VisualScriptEditor::_comment_node_resized(const Vector2 &p_new_size, int p_ graph->set_block_minimum_size_adjust(true); //faster resize - undo_redo->create_action("Resize Comment", UndoRedo::MERGE_ENDS); + undo_redo->create_action(TTR("Resize Comment"), UndoRedo::MERGE_ENDS); undo_redo->add_do_method(vsc.ptr(), "set_size", p_new_size / EDSCALE); undo_redo->add_undo_method(vsc.ptr(), "set_size", vsc->get_size()); undo_redo->commit_action(); diff --git a/modules/visual_script/visual_script_expression.cpp b/modules/visual_script/visual_script_expression.cpp index 23942fdd2a..a76e4bc36f 100644 --- a/modules/visual_script/visual_script_expression.cpp +++ b/modules/visual_script/visual_script_expression.cpp @@ -679,10 +679,10 @@ VisualScriptExpression::ENode *VisualScriptExpression::_parse_expression() { } str_ofs = cofs; //revert //parse an expression - ENode *expr = _parse_expression(); - if (!expr) + ENode *expr2 = _parse_expression(); + if (!expr2) return NULL; - dn->dict.push_back(expr); + dn->dict.push_back(expr2); _get_token(tk); if (tk.type != TK_COLON) { @@ -690,11 +690,11 @@ VisualScriptExpression::ENode *VisualScriptExpression::_parse_expression() { return NULL; } - expr = _parse_expression(); - if (!expr) + expr2 = _parse_expression(); + if (!expr2) return NULL; - dn->dict.push_back(expr); + dn->dict.push_back(expr2); cofs = str_ofs; _get_token(tk); @@ -723,10 +723,10 @@ VisualScriptExpression::ENode *VisualScriptExpression::_parse_expression() { } str_ofs = cofs; //revert //parse an expression - ENode *expr = _parse_expression(); - if (!expr) + ENode *expr2 = _parse_expression(); + if (!expr2) return NULL; - an->array.push_back(expr); + an->array.push_back(expr2); cofs = str_ofs; _get_token(tk); @@ -807,11 +807,11 @@ VisualScriptExpression::ENode *VisualScriptExpression::_parse_expression() { } str_ofs = cofs; //revert //parse an expression - ENode *expr = _parse_expression(); - if (!expr) + ENode *expr2 = _parse_expression(); + if (!expr2) return NULL; - constructor->arguments.push_back(expr); + constructor->arguments.push_back(expr2); cofs = str_ofs; _get_token(tk); @@ -848,11 +848,11 @@ VisualScriptExpression::ENode *VisualScriptExpression::_parse_expression() { } str_ofs = cofs; //revert //parse an expression - ENode *expr = _parse_expression(); - if (!expr) + ENode *expr2 = _parse_expression(); + if (!expr2) return NULL; - bifunc->arguments.push_back(expr); + bifunc->arguments.push_back(expr2); cofs = str_ofs; _get_token(tk); @@ -947,25 +947,25 @@ VisualScriptExpression::ENode *VisualScriptExpression::_parse_expression() { while (true) { - int cofs = str_ofs; + int cofs3 = str_ofs; _get_token(tk); if (tk.type == TK_PARENTHESIS_CLOSE) { break; } - str_ofs = cofs; //revert + str_ofs = cofs3; //revert //parse an expression - ENode *expr = _parse_expression(); - if (!expr) + ENode *expr2 = _parse_expression(); + if (!expr2) return NULL; - func_call->arguments.push_back(expr); + func_call->arguments.push_back(expr2); - cofs = str_ofs; + cofs3 = str_ofs; _get_token(tk); if (tk.type == TK_COMMA) { //all good } else if (tk.type == TK_PARENTHESIS_CLOSE) { - str_ofs = cofs; + str_ofs = cofs3; } else { _set_error("Expected ',' or ')'"); } @@ -1426,8 +1426,8 @@ public: for (int i = 0; i < call->arguments.size(); i++) { Variant value; - bool ret = _execute(p_inputs, call->arguments[i], value, r_error_str, ce); - if (ret) + bool ret2 = _execute(p_inputs, call->arguments[i], value, r_error_str, ce); + if (ret2) return true; arr.write[i] = value; argp.write[i] = &arr[i]; diff --git a/modules/visual_script/visual_script_property_selector.cpp b/modules/visual_script/visual_script_property_selector.cpp index 9dc0e4edfa..fa7b13bf5b 100644 --- a/modules/visual_script/visual_script_property_selector.cpp +++ b/modules/visual_script/visual_script_property_selector.cpp @@ -514,26 +514,26 @@ void VisualScriptPropertySelector::_item_selected() { if (names->find(name) != NULL) { Ref<VisualScriptOperator> operator_node = VisualScriptLanguage::singleton->create_node_from_name(name); if (operator_node.is_valid()) { - Map<String, DocData::ClassDoc>::Element *E = dd->class_list.find(operator_node->get_class_name()); - if (E) { + Map<String, DocData::ClassDoc>::Element *F = dd->class_list.find(operator_node->get_class_name()); + if (F) { text = Variant::get_operator_name(operator_node->get_operator()); } } Ref<VisualScriptTypeCast> typecast_node = VisualScriptLanguage::singleton->create_node_from_name(name); if (typecast_node.is_valid()) { - Map<String, DocData::ClassDoc>::Element *E = dd->class_list.find(typecast_node->get_class_name()); - if (E) { - text = E->get().description; + Map<String, DocData::ClassDoc>::Element *F = dd->class_list.find(typecast_node->get_class_name()); + if (F) { + text = F->get().description; } } Ref<VisualScriptBuiltinFunc> builtin_node = VisualScriptLanguage::singleton->create_node_from_name(name); if (builtin_node.is_valid()) { - Map<String, DocData::ClassDoc>::Element *E = dd->class_list.find(builtin_node->get_class_name()); - if (E) { - for (int i = 0; i < E->get().constants.size(); i++) { - if (E->get().constants[i].value.to_int() == int(builtin_node->get_func())) { - text = E->get().constants[i].description; + Map<String, DocData::ClassDoc>::Element *F = dd->class_list.find(builtin_node->get_class_name()); + if (F) { + for (int i = 0; i < F->get().constants.size(); i++) { + if (F->get().constants[i].value.to_int() == int(builtin_node->get_func())) { + text = F->get().constants[i].description; } } } diff --git a/modules/websocket/lws_client.cpp b/modules/websocket/lws_client.cpp index 2fbb46f3e2..2dce0ed1f5 100644 --- a/modules/websocket/lws_client.cpp +++ b/modules/websocket/lws_client.cpp @@ -144,9 +144,9 @@ int LWSClient::_handle_cb(struct lws *wsi, enum lws_callback_reasons reason, voi case LWS_CALLBACK_WS_PEER_INITIATED_CLOSE: { int code; - String reason = peer->get_close_reason(in, len, code); + String reason2 = peer->get_close_reason(in, len, code); peer_data->clean_close = true; - _on_close_request(code, reason); + _on_close_request(code, reason2); return 0; } diff --git a/modules/websocket/lws_peer.cpp b/modules/websocket/lws_peer.cpp index 8afcdfe62e..a7c85450fa 100644 --- a/modules/websocket/lws_peer.cpp +++ b/modules/websocket/lws_peer.cpp @@ -102,7 +102,7 @@ Error LWSPeer::write_wsi() { return OK; int read = 0; - uint8_t is_string; + uint8_t is_string = 0; PoolVector<uint8_t>::Write rw = _packet_buffer.write(); _out_buffer.read_packet(&(rw[LWS_PRE]), _packet_buffer.size() - LWS_PRE, &is_string, read); diff --git a/modules/websocket/lws_server.cpp b/modules/websocket/lws_server.cpp index fe7da99a9f..61ccdca74a 100644 --- a/modules/websocket/lws_server.cpp +++ b/modules/websocket/lws_server.cpp @@ -109,9 +109,9 @@ int LWSServer::_handle_cb(struct lws *wsi, enum lws_callback_reasons reason, voi if (_peer_map.has(id)) { int code; Ref<LWSPeer> peer = _peer_map[id]; - String reason = peer->get_close_reason(in, len, code); + String reason2 = peer->get_close_reason(in, len, code); peer_data->clean_close = true; - _on_close_request(id, code, reason); + _on_close_request(id, code, reason2); } return 0; } diff --git a/modules/websocket/websocket_client.h b/modules/websocket/websocket_client.h index 32db719435..c464d97c7f 100644 --- a/modules/websocket/websocket_client.h +++ b/modules/websocket/websocket_client.h @@ -32,7 +32,7 @@ #define WEBSOCKET_CLIENT_H #include "core/error_list.h" -#include "websocket_multiplayer.h" +#include "websocket_multiplayer_peer.h" #include "websocket_peer.h" class WebSocketClient : public WebSocketMultiplayerPeer { diff --git a/modules/websocket/websocket_multiplayer.cpp b/modules/websocket/websocket_multiplayer_peer.cpp index 11caac944b..a48738b6a4 100644 --- a/modules/websocket/websocket_multiplayer.cpp +++ b/modules/websocket/websocket_multiplayer_peer.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* websocket_multiplayer.cpp */ +/* websocket_multiplayer_peer.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,7 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "websocket_multiplayer.h" +#include "websocket_multiplayer_peer.h" + #include "core/os/os.h" WebSocketMultiplayerPeer::WebSocketMultiplayerPeer() { diff --git a/modules/websocket/websocket_multiplayer.h b/modules/websocket/websocket_multiplayer_peer.h index 1aecad97a0..b050449ee0 100644 --- a/modules/websocket/websocket_multiplayer.h +++ b/modules/websocket/websocket_multiplayer_peer.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* websocket_multiplayer.h */ +/* websocket_multiplayer_peer.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ diff --git a/modules/websocket/websocket_server.h b/modules/websocket/websocket_server.h index 3f3e46db5a..7a94c4047b 100644 --- a/modules/websocket/websocket_server.h +++ b/modules/websocket/websocket_server.h @@ -32,7 +32,7 @@ #define WEBSOCKET_H #include "core/reference.h" -#include "websocket_multiplayer.h" +#include "websocket_multiplayer_peer.h" #include "websocket_peer.h" class WebSocketServer : public WebSocketMultiplayerPeer { diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp index f293eef2ba..9d9270bdac 100644 --- a/platform/android/export/export.cpp +++ b/platform/android/export/export.cpp @@ -206,9 +206,9 @@ static const LauncherIcon launcher_icons[] = { { "launcher_icons/mdpi_48x48", "res/drawable-mdpi-v4/icon.png" } }; -class EditorExportAndroid : public EditorExportPlatform { +class EditorExportPlatformAndroid : public EditorExportPlatform { - GDCLASS(EditorExportAndroid, EditorExportPlatform) + GDCLASS(EditorExportPlatformAndroid, EditorExportPlatform) Ref<ImageTexture> logo; Ref<ImageTexture> run_icon; @@ -235,7 +235,7 @@ class EditorExportAndroid : public EditorExportPlatform { static void _device_poll_thread(void *ud) { - EditorExportAndroid *ea = (EditorExportAndroid *)ud; + EditorExportPlatformAndroid *ea = (EditorExportPlatformAndroid *)ud; while (!ea->quit_request) { @@ -301,10 +301,10 @@ class EditorExportAndroid : public EditorExportPlatform { args.push_back(d.id); args.push_back("shell"); args.push_back("getprop"); - int ec; + int ec2; String dp; - OS::get_singleton()->execute(adb, args, true, NULL, &dp, &ec); + OS::get_singleton()->execute(adb, args, true, NULL, &dp, &ec2); Vector<String> props = dp.split("\n"); String vendor; @@ -1925,7 +1925,7 @@ public: virtual void resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, Set<String> &p_features) { } - EditorExportAndroid() { + EditorExportPlatformAndroid() { Ref<Image> img = memnew(Image(_android_logo)); logo.instance(); @@ -1941,7 +1941,7 @@ public: device_thread = Thread::create(_device_poll_thread, this); } - ~EditorExportAndroid() { + ~EditorExportPlatformAndroid() { quit_request = true; Thread::wait_to_finish(device_thread); memdelete(device_lock); @@ -1969,6 +1969,6 @@ void register_android_exporter() { EDITOR_DEF("export/android/timestamping_authority_url", ""); EDITOR_DEF("export/android/shutdown_adb_on_exit", true); - Ref<EditorExportAndroid> exporter = Ref<EditorExportAndroid>(memnew(EditorExportAndroid)); + Ref<EditorExportPlatformAndroid> exporter = Ref<EditorExportPlatformAndroid>(memnew(EditorExportPlatformAndroid)); EditorExport::get_singleton()->add_export_platform(exporter); } diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp index 2ee0b34c48..3ba8468e0b 100644 --- a/platform/android/os_android.cpp +++ b/platform/android/os_android.cpp @@ -175,7 +175,7 @@ Error OS_Android::initialize(const VideoMode &p_desired, int p_video_driver, int input = memnew(InputDefault); input->set_fallback_mapping("Default Android Gamepad"); - //power_manager = memnew(power_android); + //power_manager = memnew(PowerAndroid); return OK; } diff --git a/platform/android/os_android.h b/platform/android/os_android.h index 3c591af4bb..1e5b89e24d 100644 --- a/platform/android/os_android.h +++ b/platform/android/os_android.h @@ -134,7 +134,7 @@ private: SetKeepScreenOnFunc set_keep_screen_on_func; AlertFunc alert_func; - //power_android *power_manager; + //PowerAndroid *power_manager; int video_driver_index; public: diff --git a/platform/android/power_android.cpp b/platform/android/power_android.cpp index 40b9d81189..4d2fbfbf1a 100644 --- a/platform/android/power_android.cpp +++ b/platform/android/power_android.cpp @@ -190,7 +190,7 @@ int Android_JNI_GetPowerInfo(int *plugged, int *charged, int *battery, int *seco return 0; } -bool power_android::GetPowerInfo_Android() { +bool PowerAndroid::GetPowerInfo_Android() { int battery; int plugged; int charged; @@ -218,7 +218,7 @@ bool power_android::GetPowerInfo_Android() { return true; } -OS::PowerState power_android::get_power_state() { +OS::PowerState PowerAndroid::get_power_state() { if (GetPowerInfo_Android()) { return power_state; } else { @@ -227,7 +227,7 @@ OS::PowerState power_android::get_power_state() { } } -int power_android::get_power_seconds_left() { +int PowerAndroid::get_power_seconds_left() { if (GetPowerInfo_Android()) { return nsecs_left; } else { @@ -236,7 +236,7 @@ int power_android::get_power_seconds_left() { } } -int power_android::get_power_percent_left() { +int PowerAndroid::get_power_percent_left() { if (GetPowerInfo_Android()) { return percent_left; } else { @@ -245,11 +245,11 @@ int power_android::get_power_percent_left() { } } -power_android::power_android() : +PowerAndroid::PowerAndroid() : nsecs_left(-1), percent_left(-1), power_state(OS::POWERSTATE_UNKNOWN) { } -power_android::~power_android() { +PowerAndroid::~PowerAndroid() { } diff --git a/platform/android/power_android.h b/platform/android/power_android.h index 9730c53674..6cb745b6c0 100644 --- a/platform/android/power_android.h +++ b/platform/android/power_android.h @@ -28,13 +28,14 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef PLATFORM_ANDROID_POWER_ANDROID_H_ -#define PLATFORM_ANDROID_POWER_ANDROID_H_ +#ifndef POWER_ANDROID_H +#define POWER_ANDROID_H #include "core/os/os.h" + #include <android/native_window_jni.h> -class power_android { +class PowerAndroid { struct LocalReferenceHolder { JNIEnv *m_env; @@ -65,8 +66,8 @@ private: public: static int s_active; - power_android(); - virtual ~power_android(); + PowerAndroid(); + virtual ~PowerAndroid(); static bool LocalReferenceHolder_Init(struct LocalReferenceHolder *refholder, JNIEnv *env); static struct LocalReferenceHolder LocalReferenceHolder_Setup(const char *func); static void LocalReferenceHolder_Cleanup(struct LocalReferenceHolder *refholder); @@ -76,4 +77,4 @@ public: int get_power_percent_left(); }; -#endif /* PLATFORM_ANDROID_POWER_ANDROID_H_ */ +#endif // POWER_ANDROID_H diff --git a/platform/iphone/SCsub b/platform/iphone/SCsub index d5540fe8db..41991bce86 100644 --- a/platform/iphone/SCsub +++ b/platform/iphone/SCsub @@ -7,7 +7,7 @@ import os iphone_lib = [ 'godot_iphone.cpp', 'os_iphone.cpp', - 'sem_iphone.cpp', + 'semaphore_iphone.cpp', 'gl_view.mm', 'main.m', 'app_delegate.mm', diff --git a/platform/iphone/export/export.cpp b/platform/iphone/export/export.cpp index 849e6d4a14..d234ddac27 100644 --- a/platform/iphone/export/export.cpp +++ b/platform/iphone/export/export.cpp @@ -246,7 +246,7 @@ void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options) r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/app_store_team_id"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/provisioning_profile_uuid_debug"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/code_sign_identity_debug", PROPERTY_HINT_PLACEHOLDER_TEXT, "iPhone Developer"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/code_sign_identity_debug", PROPERTY_HINT_PLACEHOLDER_TEXT, "iPhone Developer"), "iPhone Developer")); r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "application/export_method_debug", PROPERTY_HINT_ENUM, "App Store,Development,Ad-Hoc,Enterprise"), 1)); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/provisioning_profile_uuid_release"), "")); @@ -255,12 +255,27 @@ void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options) r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Game Name"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/info"), "Made with Godot Engine")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/identifier", PROPERTY_HINT_PLACEHOLDER_TEXT, "come.example.game"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/identifier", PROPERTY_HINT_PLACEHOLDER_TEXT, "com.example.game"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/signature"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/short_version"), "1.0")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/version"), "1.0")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/copyright"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "capabilities/arkit"), false)); + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "capabilities/access_wifi"), false)); + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "capabilities/game_center"), true)); + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "capabilities/in_app_purchases"), false)); + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "capabilities/push_notifications"), false)); + + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/camera_usage_description"), "Godot would like to use your camera")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/microphone_usage_description"), "Godot would like to use your microphone")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/photolibrary_usage_description"), "Godot would like to use your photos")); + + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "orientation/portrait"), true)); + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "orientation/landscape_left"), true)); + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "orientation/landscape_right"), true)); + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "orientation/portrait_upside_down"), true)); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "required_icons/iphone_120x120", PROPERTY_HINT_FILE, "*.png"), "")); // Home screen on iPhone/iPod Touch with retina display r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "required_icons/ipad_76x76", PROPERTY_HINT_FILE, "*.png"), "")); // Home screen on iPad r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "required_icons/app_store_1024x1024", PROPERTY_HINT_FILE, "*.png"), "")); // App Store @@ -337,6 +352,62 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_ strnew += lines[i].replace("$linker_flags", p_config.linker_flags) + "\n"; } else if (lines[i].find("$cpp_code") != -1) { strnew += lines[i].replace("$cpp_code", p_config.cpp_code) + "\n"; + } else if (lines[i].find("$access_wifi") != -1) { + bool is_on = p_preset->get("capabilities/access_wifi"); + strnew += lines[i].replace("$access_wifi", is_on ? "1" : "0") + "\n"; + } else if (lines[i].find("$game_center") != -1) { + bool is_on = p_preset->get("capabilities/game_center"); + strnew += lines[i].replace("$game_center", is_on ? "1" : "0") + "\n"; + } else if (lines[i].find("$in_app_purchases") != -1) { + bool is_on = p_preset->get("capabilities/in_app_purchases"); + strnew += lines[i].replace("$in_app_purchases", is_on ? "1" : "0") + "\n"; + } else if (lines[i].find("$push_notifications") != -1) { + bool is_on = p_preset->get("capabilities/push_notifications"); + strnew += lines[i].replace("$push_notifications", is_on ? "1" : "0") + "\n"; + } else if (lines[i].find("$required_device_capabilities") != -1) { + String capabilities; + + // I've removed armv7 as we can run on 64bit only devices + // Note that capabilities listed here are requirements for the app to be installed. + // They don't enable anything. + + if ((bool)p_preset->get("capabilities/arkit")) { + capabilities += "<string>arkit</string>\n"; + } + if ((bool)p_preset->get("capabilities/game_center")) { + capabilities += "<string>gamekit</string>\n"; + } + if ((bool)p_preset->get("capabilities/access_wifi")) { + capabilities += "<string>wifi</string>\n"; + } + + strnew += lines[i].replace("$required_device_capabilities", capabilities); + } else if (lines[i].find("$interface_orientations") != -1) { + String orientations; + + if ((bool)p_preset->get("orientation/portrait")) { + orientations += "<string>UIInterfaceOrientationPortrait</string>\n"; + } + if ((bool)p_preset->get("orientation/landscape_left")) { + orientations += "<string>UIInterfaceOrientationLandscapeLeft</string>\n"; + } + if ((bool)p_preset->get("orientation/landscape_right")) { + orientations += "<string>UIInterfaceOrientationLandscapeRight</string>\n"; + } + if ((bool)p_preset->get("orientation/portrait_upside_down")) { + orientations += "<string>UIInterfaceOrientationPortraitUpsideDown</string>\n"; + } + + strnew += lines[i].replace("$interface_orientations", orientations); + } else if (lines[i].find("$camera_usage_description") != -1) { + String description = p_preset->get("privacy/camera_usage_description"); + strnew += lines[i].replace("$camera_usage_description", description) + "\n"; + } else if (lines[i].find("$microphone_usage_description") != -1) { + String description = p_preset->get("privacy/microphone_usage_description"); + strnew += lines[i].replace("$microphone_usage_description", description) + "\n"; + } else if (lines[i].find("$photolibrary_usage_description") != -1) { + String description = p_preset->get("privacy/photolibrary_usage_description"); + strnew += lines[i].replace("$photolibrary_usage_description", description) + "\n"; } else { strnew += lines[i] + "\n"; } @@ -648,6 +719,10 @@ void EditorExportPlatformIOS::_add_assets_to_project(Vector<uint8_t> &p_project_ pbx_files += file_info_format.format(format_dict, "$_"); } + // Note, frameworks like gamekit are always included in our project.pbxprof file + // even if turned off in capabilities. + // Frameworks that are used by modules (like arkit) we may need to optionally add here. + String str = String::utf8((const char *)p_project_data.ptr(), p_project_data.size()); str = str.replace("$additional_pbx_files", pbx_files); str = str.replace("$additional_pbx_frameworks_build", pbx_frameworks_build); diff --git a/platform/iphone/os_iphone.cpp b/platform/iphone/os_iphone.cpp index 16634c3b30..c939e234b9 100644 --- a/platform/iphone/os_iphone.cpp +++ b/platform/iphone/os_iphone.cpp @@ -45,9 +45,10 @@ #include "core/project_settings.h" #include "drivers/unix/syslog_logger.h" -#include "sem_iphone.h" +#include "semaphore_iphone.h" #include "ios.h" + #include <dlfcn.h> int OSIPhone::get_video_driver_count() const { diff --git a/platform/iphone/power_iphone.h b/platform/iphone/power_iphone.h index eb930b99c5..d7d4bf4a69 100644 --- a/platform/iphone/power_iphone.h +++ b/platform/iphone/power_iphone.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef PLATFORM_IPHONE_POWER_IPHONE_H_ -#define PLATFORM_IPHONE_POWER_IPHONE_H_ +#ifndef POWER_IPHONE_H +#define POWER_IPHONE_H #include <os/os.h> @@ -50,4 +50,4 @@ public: int get_power_percent_left(); }; -#endif /* PLATFORM_IPHONE_POWER_IPHONE_H_ */ +#endif // POWER_IPHONE_H diff --git a/platform/iphone/sem_iphone.cpp b/platform/iphone/semaphore_iphone.cpp index 05cdb6a2f7..cc7dde72f7 100644 --- a/platform/iphone/sem_iphone.cpp +++ b/platform/iphone/semaphore_iphone.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* sem_iphone.cpp */ +/* semaphore_iphone.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,7 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "sem_iphone.h" +#include "semaphore_iphone.h" #include <fcntl.h> #include <unistd.h> @@ -71,6 +71,7 @@ void cgsem_destroy(cgsem_t *cgsem) { } #include "core/os/memory.h" + #include <errno.h> Error SemaphoreIphone::wait() { diff --git a/platform/iphone/sem_iphone.h b/platform/iphone/semaphore_iphone.h index 134bc723d9..16658384e6 100644 --- a/platform/iphone/sem_iphone.h +++ b/platform/iphone/semaphore_iphone.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* sem_iphone.h */ +/* semaphore_iphone.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef SEM_IPHONE_H -#define SEM_IPHONE_H +#ifndef SEMAPHORE_IPHONE_H +#define SEMAPHORE_IPHONE_H struct cgsem { int pipefd[2]; @@ -56,4 +56,4 @@ public: ~SemaphoreIphone(); }; -#endif +#endif // SEMAPHORE_IPHONE_H diff --git a/platform/javascript/detect.py b/platform/javascript/detect.py index 22b5f1f87a..c3f3946ee0 100644 --- a/platform/javascript/detect.py +++ b/platform/javascript/detect.py @@ -130,7 +130,7 @@ def configure(env): env.Append(LINKFLAGS=['-s', 'ALLOW_MEMORY_GROWTH=1']) # Since we use both memory growth and MEMFS preloading, - # this avoids unecessary copying on start-up. + # this avoids unnecessary copying on start-up. env.Append(LINKFLAGS=['--no-heap-copy']) # This setting just makes WebGL 2 APIs available, it does NOT disable WebGL 1. diff --git a/platform/osx/SCsub b/platform/osx/SCsub index dc407eee9e..d2952ebdc0 100644 --- a/platform/osx/SCsub +++ b/platform/osx/SCsub @@ -10,7 +10,7 @@ files = [ 'crash_handler_osx.mm', 'os_osx.mm', 'godot_main_osx.mm', - 'sem_osx.cpp', + 'semaphore_osx.cpp', 'dir_access_osx.mm', 'joypad_osx.cpp', 'power_osx.cpp', diff --git a/platform/osx/crash_handler_osx.h b/platform/osx/crash_handler_osx.h index dead90ca90..6a72ce8ae9 100644 --- a/platform/osx/crash_handler_osx.h +++ b/platform/osx/crash_handler_osx.h @@ -45,4 +45,4 @@ public: ~CrashHandler(); }; -#endif +#endif // CRASH_HANDLER_OSX_H diff --git a/platform/osx/crash_handler_osx.mm b/platform/osx/crash_handler_osx.mm index 6684898085..ed8a955ae5 100644 --- a/platform/osx/crash_handler_osx.mm +++ b/platform/osx/crash_handler_osx.mm @@ -28,9 +28,11 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#include "crash_handler_osx.h" + +#include "core/os/os.h" #include "core/project_settings.h" #include "main/main.h" -#include "os_osx.h" #include <string.h> #include <unistd.h> diff --git a/platform/osx/os_osx.h b/platform/osx/os_osx.h index 927c8c9b00..dfe7b27bd0 100644 --- a/platform/osx/os_osx.h +++ b/platform/osx/os_osx.h @@ -34,7 +34,7 @@ #include "core/os/input.h" #include "crash_handler_osx.h" #include "drivers/coreaudio/audio_driver_coreaudio.h" -#include "drivers/coremidi/core_midi.h" +#include "drivers/coremidi/midi_driver_coremidi.h" #include "drivers/unix/os_unix.h" #include "joypad_osx.h" #include "main/input_default.h" @@ -43,6 +43,7 @@ #include "servers/visual/rasterizer.h" #include "servers/visual/visual_server_wrap_mt.h" #include "servers/visual_server.h" + #include <AppKit/AppKit.h> #include <AppKit/NSCursor.h> #include <ApplicationServices/ApplicationServices.h> @@ -132,7 +133,7 @@ public: String im_text; Point2 im_selection; - power_osx *power_manager; + PowerOSX *power_manager; CrashHandler crash_handler; diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm index 3f80d19fa1..225e0aee06 100644 --- a/platform/osx/os_osx.mm +++ b/platform/osx/os_osx.mm @@ -37,7 +37,7 @@ #include "drivers/gles2/rasterizer_gles2.h" #include "drivers/gles3/rasterizer_gles3.h" #include "main/main.h" -#include "sem_osx.h" +#include "semaphore_osx.h" #include "servers/visual/visual_server_raster.h" #include <mach-o/dyld.h> @@ -282,7 +282,9 @@ static CVReturn DisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeSt NSWindow *window = (NSWindow *)[notification object]; CGFloat newBackingScaleFactor = [window backingScaleFactor]; CGFloat oldBackingScaleFactor = [[[notification userInfo] objectForKey:@"NSBackingPropertyOldScaleFactorKey"] doubleValue]; - [OS_OSX::singleton->window_view setWantsBestResolutionOpenGLSurface:YES]; + if (OS_OSX::singleton->is_hidpi_allowed()) { + [OS_OSX::singleton->window_view setWantsBestResolutionOpenGLSurface:YES]; + } if (newBackingScaleFactor != oldBackingScaleFactor) { //Set new display scale and window size @@ -1459,7 +1461,7 @@ Error OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_a input = memnew(InputDefault); joypad_osx = memnew(JoypadOSX); - power_manager = memnew(power_osx); + power_manager = memnew(PowerOSX); _ensure_user_data_dir(); diff --git a/platform/osx/power_osx.cpp b/platform/osx/power_osx.cpp index a7cf9d831f..04d423d8c5 100644 --- a/platform/osx/power_osx.cpp +++ b/platform/osx/power_osx.cpp @@ -67,7 +67,7 @@ Adapted from corresponding SDL 2.0 code. CFDictionaryGetValueIfPresent(dict, CFSTR(k), (const void **)v) /* Note that AC power sources also include a laptop battery it is charging. */ -void power_osx::checkps(CFDictionaryRef dict, bool *have_ac, bool *have_battery, bool *charging) { +void PowerOSX::checkps(CFDictionaryRef dict, bool *have_ac, bool *have_battery, bool *charging) { CFStringRef strval; /* don't CFRelease() this. */ CFBooleanRef bval; CFNumberRef numval; @@ -169,7 +169,7 @@ void power_osx::checkps(CFDictionaryRef dict, bool *have_ac, bool *have_battery, #undef STRMATCH // CODE CHUNK IMPORTED FROM SDL 2.0 -bool power_osx::GetPowerInfo_MacOSX() { +bool PowerOSX::GetPowerInfo_MacOSX() { CFTypeRef blob = IOPSCopyPowerSourcesInfo(); nsecs_left = -1; @@ -211,14 +211,14 @@ bool power_osx::GetPowerInfo_MacOSX() { return true; /* always the definitive answer on Mac OS X. */ } -bool power_osx::UpdatePowerInfo() { +bool PowerOSX::UpdatePowerInfo() { if (GetPowerInfo_MacOSX()) { return true; } return false; } -OS::PowerState power_osx::get_power_state() { +OS::PowerState PowerOSX::get_power_state() { if (UpdatePowerInfo()) { return power_state; } else { @@ -226,7 +226,7 @@ OS::PowerState power_osx::get_power_state() { } } -int power_osx::get_power_seconds_left() { +int PowerOSX::get_power_seconds_left() { if (UpdatePowerInfo()) { return nsecs_left; } else { @@ -234,7 +234,7 @@ int power_osx::get_power_seconds_left() { } } -int power_osx::get_power_percent_left() { +int PowerOSX::get_power_percent_left() { if (UpdatePowerInfo()) { return percent_left; } else { @@ -242,11 +242,11 @@ int power_osx::get_power_percent_left() { } } -power_osx::power_osx() : +PowerOSX::PowerOSX() : nsecs_left(-1), percent_left(-1), power_state(OS::POWERSTATE_UNKNOWN) { } -power_osx::~power_osx() { +PowerOSX::~PowerOSX() { } diff --git a/platform/osx/power_osx.h b/platform/osx/power_osx.h index 0f18f9f691..40d0d40fd4 100644 --- a/platform/osx/power_osx.h +++ b/platform/osx/power_osx.h @@ -28,15 +28,16 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef PLATFORM_OSX_POWER_OSX_H_ -#define PLATFORM_OSX_POWER_OSX_H_ +#ifndef POWER_OSX_H +#define POWER_OSX_H #include "core/os/file_access.h" #include "core/os/os.h" #include "dir_access_osx.h" + #include <CoreFoundation/CoreFoundation.h> -class power_osx { +class PowerOSX { private: int nsecs_left; @@ -47,12 +48,12 @@ private: bool UpdatePowerInfo(); public: - power_osx(); - virtual ~power_osx(); + PowerOSX(); + virtual ~PowerOSX(); OS::PowerState get_power_state(); int get_power_seconds_left(); int get_power_percent_left(); }; -#endif /* PLATFORM_OSX_POWER_OSX_H_ */ +#endif // POWER_OSX_H diff --git a/platform/osx/sem_osx.cpp b/platform/osx/semaphore_osx.cpp index 4c3bad4379..fe7d19bd9e 100644 --- a/platform/osx/sem_osx.cpp +++ b/platform/osx/semaphore_osx.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* sem_osx.cpp */ +/* semaphore_osx.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,7 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "sem_osx.h" +#include "semaphore_osx.h" #include <fcntl.h> #include <unistd.h> @@ -66,6 +66,7 @@ void cgsem_destroy(cgsem_t *cgsem) { } #include "core/os/memory.h" + #include <errno.h> Error SemaphoreOSX::wait() { diff --git a/platform/osx/sem_osx.h b/platform/osx/semaphore_osx.h index 563bdfdcb1..c8e7c45227 100644 --- a/platform/osx/sem_osx.h +++ b/platform/osx/semaphore_osx.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* sem_osx.h */ +/* semaphore_osx.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef SEM_OSX_H -#define SEM_OSX_H +#ifndef SEMAPHORE_OSX_H +#define SEMAPHORE_OSX_H struct cgsem { int pipefd[2]; @@ -56,4 +56,4 @@ public: ~SemaphoreOSX(); }; -#endif +#endif // SEMAPHORE_OSX_H diff --git a/platform/server/SCsub b/platform/server/SCsub index 51fd05a87e..62d45efbc0 100644 --- a/platform/server/SCsub +++ b/platform/server/SCsub @@ -13,7 +13,7 @@ common_server = [\ if sys.platform == "darwin": common_server.append("#platform/osx/crash_handler_osx.mm") common_server.append("#platform/osx/power_osx.cpp") - common_server.append("#platform/osx/sem_osx.cpp") + common_server.append("#platform/osx/semaphore_osx.cpp") else: common_server.append("#platform/x11/crash_handler_x11.cpp") common_server.append("#platform/x11/power_x11.cpp") diff --git a/platform/server/os_server.cpp b/platform/server/os_server.cpp index 9b6e7864e1..e643d3e8bb 100644 --- a/platform/server/os_server.cpp +++ b/platform/server/os_server.cpp @@ -93,7 +93,7 @@ Error OS_Server::initialize(const VideoMode &p_desired, int p_video_driver, int input = memnew(InputDefault); #ifdef __APPLE__ - power_manager = memnew(power_osx); + power_manager = memnew(PowerOSX); #else power_manager = memnew(PowerX11); #endif diff --git a/platform/server/os_server.h b/platform/server/os_server.h index 7273a690ca..eebe8ae777 100644 --- a/platform/server/os_server.h +++ b/platform/server/os_server.h @@ -32,13 +32,12 @@ #define OS_SERVER_H #include "drivers/dummy/texture_loader_dummy.h" -#include "drivers/rtaudio/audio_driver_rtaudio.h" #include "drivers/unix/os_unix.h" #include "main/input_default.h" #ifdef __APPLE__ #include "platform/osx/crash_handler_osx.h" #include "platform/osx/power_osx.h" -#include "platform/osx/sem_osx.h" +#include "platform/osx/semaphore_osx.h" #else #include "platform/x11/crash_handler_x11.h" #include "platform/x11/power_x11.h" @@ -69,7 +68,7 @@ class OS_Server : public OS_Unix { InputDefault *input; #ifdef __APPLE__ - power_osx *power_manager; + PowerOSX *power_manager; #else PowerX11 *power_manager; #endif diff --git a/platform/uwp/SCsub b/platform/uwp/SCsub index fb0c4a92ae..c14290f0c4 100644 --- a/platform/uwp/SCsub +++ b/platform/uwp/SCsub @@ -4,11 +4,11 @@ Import('env') files = [ 'thread_uwp.cpp', - '#platform/windows/key_mapping_win.cpp', + '#platform/windows/key_mapping_windows.cpp', '#platform/windows/windows_terminal_logger.cpp', 'joypad_uwp.cpp', 'power_uwp.cpp', - 'gl_context_egl.cpp', + 'context_egl_uwp.cpp', 'app.cpp', 'os_uwp.cpp', ] diff --git a/platform/uwp/app.cpp b/platform/uwp/app.cpp index 1b8f9f3f9e..4f2ee0237a 100644 --- a/platform/uwp/app.cpp +++ b/platform/uwp/app.cpp @@ -39,7 +39,7 @@ #include "core/os/keyboard.h" #include "main/main.h" -#include "platform/windows/key_mapping_win.h" +#include "platform/windows/key_mapping_windows.h" #include <collection.h> @@ -99,7 +99,7 @@ void App::Initialize(CoreApplicationView ^ applicationView) { // Information about the Suspending and Resuming event handlers can be found here: // http://msdn.microsoft.com/en-us/library/windows/apps/xaml/hh994930.aspx - os = new OSUWP; + os = new OS_UWP; } // Called when the CoreWindow object is created (or re-created). @@ -398,7 +398,7 @@ void App::OnMouseMoved(MouseDevice ^ mouse_device, MouseEventArgs ^ args) { void App::key_event(Windows::UI::Core::CoreWindow ^ sender, bool p_pressed, Windows::UI::Core::KeyEventArgs ^ key_args, Windows::UI::Core::CharacterReceivedEventArgs ^ char_args) { - OSUWP::KeyEvent ke; + OS_UWP::KeyEvent ke; ke.control = sender->GetAsyncKeyState(VirtualKey::Control) == CoreVirtualKeyStates::Down; ke.alt = sender->GetAsyncKeyState(VirtualKey::Menu) == CoreVirtualKeyStates::Down; @@ -408,14 +408,14 @@ void App::key_event(Windows::UI::Core::CoreWindow ^ sender, bool p_pressed, Wind if (key_args != nullptr) { - ke.type = OSUWP::KeyEvent::MessageType::KEY_EVENT_MESSAGE; + ke.type = OS_UWP::KeyEvent::MessageType::KEY_EVENT_MESSAGE; ke.unicode = 0; ke.scancode = KeyMappingWindows::get_keysym((unsigned int)key_args->VirtualKey); ke.echo = (!p_pressed && !key_args->KeyStatus.IsKeyReleased) || (p_pressed && key_args->KeyStatus.WasKeyDown); } else { - ke.type = OSUWP::KeyEvent::MessageType::CHAR_EVENT_MESSAGE; + ke.type = OS_UWP::KeyEvent::MessageType::CHAR_EVENT_MESSAGE; ke.unicode = char_args->KeyCode; ke.scancode = 0; ke.echo = (!p_pressed && !char_args->KeyStatus.IsKeyReleased) || (p_pressed && char_args->KeyStatus.WasKeyDown); diff --git a/platform/uwp/app.h b/platform/uwp/app.h index d403dace9d..0bd996d483 100644 --- a/platform/uwp/app.h +++ b/platform/uwp/app.h @@ -103,7 +103,7 @@ namespace GodotUWP EGLSurface mEglSurface; CoreWindow^ window; - OSUWP* os; + OS_UWP* os; int last_touch_x[32]; // 20 fingers, index 31 reserved for the mouse int last_touch_y[32]; diff --git a/platform/uwp/gl_context_egl.cpp b/platform/uwp/context_egl_uwp.cpp index db15be3e06..061c54687c 100644 --- a/platform/uwp/gl_context_egl.cpp +++ b/platform/uwp/context_egl_uwp.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* gl_context_egl.cpp */ +/* context_egl_uwp.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,33 +28,33 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "gl_context_egl.h" +#include "context_egl_uwp.h" #include "EGL/eglext.h" using Platform::Exception; -void ContextEGL::release_current() { +void ContextEGL_UWP::release_current() { eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, mEglContext); }; -void ContextEGL::make_current() { +void ContextEGL_UWP::make_current() { eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext); }; -int ContextEGL::get_window_width() { +int ContextEGL_UWP::get_window_width() { return width; }; -int ContextEGL::get_window_height() { +int ContextEGL_UWP::get_window_height() { return height; }; -void ContextEGL::reset() { +void ContextEGL_UWP::reset() { cleanup(); @@ -62,7 +62,7 @@ void ContextEGL::reset() { initialize(); }; -void ContextEGL::swap_buffers() { +void ContextEGL_UWP::swap_buffers() { if (eglSwapBuffers(mEglDisplay, mEglSurface) != EGL_TRUE) { cleanup(); @@ -74,7 +74,7 @@ void ContextEGL::swap_buffers() { } }; -Error ContextEGL::initialize() { +Error ContextEGL_UWP::initialize() { EGLint configAttribList[] = { EGL_RED_SIZE, 8, @@ -190,7 +190,7 @@ Error ContextEGL::initialize() { return OK; }; -void ContextEGL::cleanup() { +void ContextEGL_UWP::cleanup() { if (mEglDisplay != EGL_NO_DISPLAY && mEglSurface != EGL_NO_SURFACE) { eglDestroySurface(mEglDisplay, mEglSurface); @@ -208,14 +208,14 @@ void ContextEGL::cleanup() { } }; -ContextEGL::ContextEGL(CoreWindow ^ p_window, Driver p_driver) : +ContextEGL_UWP::ContextEGL_UWP(CoreWindow ^ p_window, Driver p_driver) : mEglDisplay(EGL_NO_DISPLAY), mEglContext(EGL_NO_CONTEXT), mEglSurface(EGL_NO_SURFACE), driver(p_driver), window(p_window) {} -ContextEGL::~ContextEGL() { +ContextEGL_UWP::~ContextEGL_UWP() { cleanup(); }; diff --git a/platform/uwp/gl_context_egl.h b/platform/uwp/context_egl_uwp.h index 60feed2e24..812bdfb688 100644 --- a/platform/uwp/gl_context_egl.h +++ b/platform/uwp/context_egl_uwp.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* gl_context_egl.h */ +/* context_egl_uwp.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,19 +28,20 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef CONTEXT_EGL_H -#define CONTEXT_EGL_H +#ifndef CONTEXT_EGL_UWP_H +#define CONTEXT_EGL_UWP_H #include <wrl.h> -#include "EGL/egl.h" +#include <EGL/egl.h> + #include "core/error_list.h" #include "core/os/os.h" #include "drivers/gl_context/context_gl.h" using namespace Windows::UI::Core; -class ContextEGL : public ContextGL { +class ContextEGL_UWP : public ContextGL { public: enum Driver { @@ -79,8 +80,8 @@ public: void cleanup(); - ContextEGL(CoreWindow ^ p_window, Driver p_driver); - virtual ~ContextEGL(); + ContextEGL_UWP(CoreWindow ^ p_window, Driver p_driver); + virtual ~ContextEGL_UWP(); }; -#endif +#endif // CONTEXT_EGL_UWP_H diff --git a/platform/uwp/detect.py b/platform/uwp/detect.py index f25b9ba9cd..c32a11b396 100644 --- a/platform/uwp/detect.py +++ b/platform/uwp/detect.py @@ -29,7 +29,6 @@ def get_opts(): return [ ('msvc_version', 'MSVC version to use (ignored if the VCINSTALLDIR environment variable is set)', None), - BoolVariable('use_mingw', 'Use the MinGW compiler even if MSVC is installed (only used on Windows)', False), ] diff --git a/platform/uwp/export/export.cpp b/platform/uwp/export/export.cpp index 6808016f13..a4655117a7 100644 --- a/platform/uwp/export/export.cpp +++ b/platform/uwp/export/export.cpp @@ -646,9 +646,9 @@ AppxPackager::~AppxPackager() {} //////////////////////////////////////////////////////////////////// -class EditorExportUWP : public EditorExportPlatform { +class EditorExportPlatformUWP : public EditorExportPlatform { - GDCLASS(EditorExportUWP, EditorExportPlatform); + GDCLASS(EditorExportPlatformUWP, EditorExportPlatform); Ref<ImageTexture> logo; @@ -1035,13 +1035,13 @@ public: r_features->push_back("s3tc"); r_features->push_back("etc"); switch ((int)p_preset->get("architecture/target")) { - case EditorExportUWP::ARM: { + case EditorExportPlatformUWP::ARM: { r_features->push_back("arm"); } break; - case EditorExportUWP::X86: { + case EditorExportPlatformUWP::X86: { r_features->push_back("32"); } break; - case EditorExportUWP::X64: { + case EditorExportPlatformUWP::X64: { r_features->push_back("64"); } break; } @@ -1123,13 +1123,13 @@ public: String platform_infix; switch (arch) { - case EditorExportUWP::ARM: { + case EditorExportPlatformUWP::ARM: { platform_infix = "arm"; } break; - case EditorExportUWP::X86: { + case EditorExportPlatformUWP::X86: { platform_infix = "x86"; } break; - case EditorExportUWP::X64: { + case EditorExportPlatformUWP::X64: { platform_infix = "x64"; } break; } @@ -1459,7 +1459,7 @@ public: virtual void resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, Set<String> &p_features) { } - EditorExportUWP() { + EditorExportPlatformUWP() { Ref<Image> img = memnew(Image(_uwp_logo)); logo.instance(); logo->create_from_image(img); @@ -1478,7 +1478,7 @@ void register_uwp_exporter() { EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::INT, "export/uwp/debug_algorithm", PROPERTY_HINT_ENUM, "MD5,SHA1,SHA256")); #endif // WINDOWS_ENABLED - Ref<EditorExportUWP> exporter; + Ref<EditorExportPlatformUWP> exporter; exporter.instance(); EditorExport::get_singleton()->add_export_platform(exporter); } diff --git a/platform/uwp/os_uwp.cpp b/platform/uwp/os_uwp.cpp index ea4f63b49c..520e179611 100644 --- a/platform/uwp/os_uwp.cpp +++ b/platform/uwp/os_uwp.cpp @@ -67,22 +67,22 @@ using namespace Windows::Devices::Sensors; using namespace Windows::ApplicationModel::DataTransfer; using namespace concurrency; -int OSUWP::get_video_driver_count() const { +int OS_UWP::get_video_driver_count() const { return 2; } -Size2 OSUWP::get_window_size() const { +Size2 OS_UWP::get_window_size() const { Size2 size; size.width = video_mode.width; size.height = video_mode.height; return size; } -int OSUWP::get_current_video_driver() const { +int OS_UWP::get_current_video_driver() const { return video_driver_index; } -void OSUWP::set_window_size(const Size2 p_size) { +void OS_UWP::set_window_size(const Size2 p_size) { Windows::Foundation::Size new_size; new_size.Width = p_size.width; @@ -97,7 +97,7 @@ void OSUWP::set_window_size(const Size2 p_size) { } } -void OSUWP::set_window_fullscreen(bool p_enabled) { +void OS_UWP::set_window_fullscreen(bool p_enabled) { ApplicationView ^ view = ApplicationView::GetForCurrentView(); @@ -117,12 +117,12 @@ void OSUWP::set_window_fullscreen(bool p_enabled) { } } -bool OSUWP::is_window_fullscreen() const { +bool OS_UWP::is_window_fullscreen() const { return ApplicationView::GetForCurrentView()->IsFullScreenMode; } -void OSUWP::set_keep_screen_on(bool p_enabled) { +void OS_UWP::set_keep_screen_on(bool p_enabled) { if (is_keep_screen_on() == p_enabled) return; @@ -134,7 +134,7 @@ void OSUWP::set_keep_screen_on(bool p_enabled) { OS::set_keep_screen_on(p_enabled); } -void OSUWP::initialize_core() { +void OS_UWP::initialize_core() { last_button_state = 0; @@ -167,36 +167,36 @@ void OSUWP::initialize_core() { cursor_shape = CURSOR_ARROW; } -bool OSUWP::can_draw() const { +bool OS_UWP::can_draw() const { return !minimized; }; -void OSUWP::set_window(Windows::UI::Core::CoreWindow ^ p_window) { +void OS_UWP::set_window(Windows::UI::Core::CoreWindow ^ p_window) { window = p_window; } -void OSUWP::screen_size_changed() { +void OS_UWP::screen_size_changed() { gl_context->reset(); }; -Error OSUWP::initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver) { +Error OS_UWP::initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver) { main_loop = NULL; outside = true; - ContextEGL::Driver opengl_api_type = ContextEGL::GLES_2_0; + ContextEGL_UWP::Driver opengl_api_type = ContextEGL_UWP::GLES_2_0; if (p_video_driver == VIDEO_DRIVER_GLES2) { - opengl_api_type = ContextEGL::GLES_2_0; + opengl_api_type = ContextEGL_UWP::GLES_2_0; } bool gl_initialization_error = false; gl_context = NULL; while (!gl_context) { - gl_context = memnew(ContextEGL(window, opengl_api_type)); + gl_context = memnew(ContextEGL_UWP(window, opengl_api_type)); if (gl_context->initialize() != OK) { memdelete(gl_context); @@ -209,7 +209,7 @@ Error OSUWP::initialize(const VideoMode &p_desired, int p_video_driver, int p_au } p_video_driver = VIDEO_DRIVER_GLES2; - opengl_api_type = ContextEGL::GLES_2_0; + opengl_api_type = ContextEGL_UWP::GLES_2_0; } else { gl_initialization_error = true; break; @@ -218,7 +218,7 @@ Error OSUWP::initialize(const VideoMode &p_desired, int p_video_driver, int p_au } while (true) { - if (opengl_api_type == ContextEGL::GLES_3_0) { + if (opengl_api_type == ContextEGL_UWP::GLES_3_0) { if (RasterizerGLES3::is_viable() == OK) { RasterizerGLES3::register_config(); RasterizerGLES3::make_current(); @@ -226,7 +226,7 @@ Error OSUWP::initialize(const VideoMode &p_desired, int p_video_driver, int p_au } else { if (GLOBAL_GET("rendering/quality/driver/driver_fallback") == "Best") { p_video_driver = VIDEO_DRIVER_GLES2; - opengl_api_type = ContextEGL::GLES_2_0; + opengl_api_type = ContextEGL_UWP::GLES_2_0; continue; } else { gl_initialization_error = true; @@ -235,7 +235,7 @@ Error OSUWP::initialize(const VideoMode &p_desired, int p_video_driver, int p_au } } - if (opengl_api_type == ContextEGL::GLES_2_0) { + if (opengl_api_type == ContextEGL_UWP::GLES_2_0) { if (RasterizerGLES2::is_viable() == OK) { RasterizerGLES2::register_config(); RasterizerGLES2::make_current(); @@ -349,7 +349,7 @@ Error OSUWP::initialize(const VideoMode &p_desired, int p_video_driver, int p_au return OK; } -void OSUWP::set_clipboard(const String &p_text) { +void OS_UWP::set_clipboard(const String &p_text) { DataPackage ^ clip = ref new DataPackage(); clip->RequestedOperation = DataPackageOperation::Copy; @@ -358,7 +358,7 @@ void OSUWP::set_clipboard(const String &p_text) { Clipboard::SetContent(clip); }; -String OSUWP::get_clipboard() const { +String OS_UWP::get_clipboard() const { if (managed_object->clipboard != nullptr) return managed_object->clipboard->Data(); @@ -366,25 +366,25 @@ String OSUWP::get_clipboard() const { return ""; }; -void OSUWP::input_event(const Ref<InputEvent> &p_event) { +void OS_UWP::input_event(const Ref<InputEvent> &p_event) { input->parse_input_event(p_event); }; -void OSUWP::delete_main_loop() { +void OS_UWP::delete_main_loop() { if (main_loop) memdelete(main_loop); main_loop = NULL; } -void OSUWP::set_main_loop(MainLoop *p_main_loop) { +void OS_UWP::set_main_loop(MainLoop *p_main_loop) { input->set_main_loop(p_main_loop); main_loop = p_main_loop; } -void OSUWP::finalize() { +void OS_UWP::finalize() { if (main_loop) memdelete(main_loop); @@ -403,19 +403,19 @@ void OSUWP::finalize() { joypad = nullptr; } -void OSUWP::finalize_core() { +void OS_UWP::finalize_core() { NetSocketPosix::cleanup(); } -void OSUWP::alert(const String &p_alert, const String &p_title) { +void OS_UWP::alert(const String &p_alert, const String &p_title) { Platform::String ^ alert = ref new Platform::String(p_alert.c_str()); Platform::String ^ title = ref new Platform::String(p_title.c_str()); MessageDialog ^ msg = ref new MessageDialog(alert, title); - UICommand ^ close = ref new UICommand("Close", ref new UICommandInvokedHandler(managed_object, &OSUWP::ManagedType::alert_close)); + UICommand ^ close = ref new UICommand("Close", ref new UICommandInvokedHandler(managed_object, &OS_UWP::ManagedType::alert_close)); msg->Commands->Append(close); msg->DefaultCommandIndex = 0; @@ -424,17 +424,17 @@ void OSUWP::alert(const String &p_alert, const String &p_title) { msg->ShowAsync(); } -void OSUWP::ManagedType::alert_close(IUICommand ^ command) { +void OS_UWP::ManagedType::alert_close(IUICommand ^ command) { alert_close_handle = false; } -void OSUWP::ManagedType::on_clipboard_changed(Platform::Object ^ sender, Platform::Object ^ ev) { +void OS_UWP::ManagedType::on_clipboard_changed(Platform::Object ^ sender, Platform::Object ^ ev) { update_clipboard(); } -void OSUWP::ManagedType::update_clipboard() { +void OS_UWP::ManagedType::update_clipboard() { DataPackageView ^ data = Clipboard::GetContent(); @@ -446,7 +446,7 @@ void OSUWP::ManagedType::update_clipboard() { } } -void OSUWP::ManagedType::on_accelerometer_reading_changed(Accelerometer ^ sender, AccelerometerReadingChangedEventArgs ^ args) { +void OS_UWP::ManagedType::on_accelerometer_reading_changed(Accelerometer ^ sender, AccelerometerReadingChangedEventArgs ^ args) { AccelerometerReading ^ reading = args->Reading; @@ -456,7 +456,7 @@ void OSUWP::ManagedType::on_accelerometer_reading_changed(Accelerometer ^ sender reading->AccelerationZ)); } -void OSUWP::ManagedType::on_magnetometer_reading_changed(Magnetometer ^ sender, MagnetometerReadingChangedEventArgs ^ args) { +void OS_UWP::ManagedType::on_magnetometer_reading_changed(Magnetometer ^ sender, MagnetometerReadingChangedEventArgs ^ args) { MagnetometerReading ^ reading = args->Reading; @@ -466,7 +466,7 @@ void OSUWP::ManagedType::on_magnetometer_reading_changed(Magnetometer ^ sender, reading->MagneticFieldZ)); } -void OSUWP::ManagedType::on_gyroscope_reading_changed(Gyrometer ^ sender, GyrometerReadingChangedEventArgs ^ args) { +void OS_UWP::ManagedType::on_gyroscope_reading_changed(Gyrometer ^ sender, GyrometerReadingChangedEventArgs ^ args) { GyrometerReading ^ reading = args->Reading; @@ -476,7 +476,7 @@ void OSUWP::ManagedType::on_gyroscope_reading_changed(Gyrometer ^ sender, Gyrome reading->AngularVelocityZ)); } -void OSUWP::set_mouse_mode(MouseMode p_mode) { +void OS_UWP::set_mouse_mode(MouseMode p_mode) { if (p_mode == MouseMode::MOUSE_MODE_CAPTURED) { @@ -501,41 +501,41 @@ void OSUWP::set_mouse_mode(MouseMode p_mode) { SetEvent(mouse_mode_changed); } -OSUWP::MouseMode OSUWP::get_mouse_mode() const { +OS_UWP::MouseMode OS_UWP::get_mouse_mode() const { return mouse_mode; } -Point2 OSUWP::get_mouse_position() const { +Point2 OS_UWP::get_mouse_position() const { return Point2(old_x, old_y); } -int OSUWP::get_mouse_button_state() const { +int OS_UWP::get_mouse_button_state() const { return last_button_state; } -void OSUWP::set_window_title(const String &p_title) { +void OS_UWP::set_window_title(const String &p_title) { } -void OSUWP::set_video_mode(const VideoMode &p_video_mode, int p_screen) { +void OS_UWP::set_video_mode(const VideoMode &p_video_mode, int p_screen) { video_mode = p_video_mode; } -OS::VideoMode OSUWP::get_video_mode(int p_screen) const { +OS::VideoMode OS_UWP::get_video_mode(int p_screen) const { return video_mode; } -void OSUWP::get_fullscreen_mode_list(List<VideoMode> *p_list, int p_screen) const { +void OS_UWP::get_fullscreen_mode_list(List<VideoMode> *p_list, int p_screen) const { } -String OSUWP::get_name() { +String OS_UWP::get_name() { return "UWP"; } -OS::Date OSUWP::get_date(bool utc) const { +OS::Date OS_UWP::get_date(bool utc) const { SYSTEMTIME systemtime; if (utc) @@ -551,7 +551,7 @@ OS::Date OSUWP::get_date(bool utc) const { date.dst = false; return date; } -OS::Time OSUWP::get_time(bool utc) const { +OS::Time OS_UWP::get_time(bool utc) const { SYSTEMTIME systemtime; if (utc) @@ -566,7 +566,7 @@ OS::Time OSUWP::get_time(bool utc) const { return time; } -OS::TimeZoneInfo OSUWP::get_time_zone_info() const { +OS::TimeZoneInfo OS_UWP::get_time_zone_info() const { TIME_ZONE_INFORMATION info; bool daylight = false; if (GetTimeZoneInformation(&info) == TIME_ZONE_ID_DAYLIGHT) @@ -579,11 +579,13 @@ OS::TimeZoneInfo OSUWP::get_time_zone_info() const { ret.name = info.StandardName; } - ret.bias = info.Bias; + // Bias value returned by GetTimeZoneInformation is inverted of what we expect + // For example on GMT-3 GetTimeZoneInformation return a Bias of 180, so invert the value to get -180 + ret.bias = -info.Bias; return ret; } -uint64_t OSUWP::get_unix_time() const { +uint64_t OS_UWP::get_unix_time() const { FILETIME ft; SYSTEMTIME st; @@ -605,14 +607,14 @@ uint64_t OSUWP::get_unix_time() const { return (*(uint64_t *)&ft - *(uint64_t *)&fep) / 10000000; }; -void OSUWP::delay_usec(uint32_t p_usec) const { +void OS_UWP::delay_usec(uint32_t p_usec) const { int msec = p_usec < 1000 ? 1 : p_usec / 1000; // no Sleep() WaitForSingleObjectEx(GetCurrentThread(), msec, false); } -uint64_t OSUWP::get_ticks_usec() const { +uint64_t OS_UWP::get_ticks_usec() const { uint64_t ticks; uint64_t time; @@ -626,13 +628,13 @@ uint64_t OSUWP::get_ticks_usec() const { return time; } -void OSUWP::process_events() { +void OS_UWP::process_events() { joypad->process_controllers(); process_key_events(); } -void OSUWP::process_key_events() { +void OS_UWP::process_key_events() { for (int i = 0; i < key_event_pos; i++) { @@ -653,7 +655,7 @@ void OSUWP::process_key_events() { key_event_pos = 0; } -void OSUWP::queue_key_event(KeyEvent &p_event) { +void OS_UWP::queue_key_event(KeyEvent &p_event) { // This merges Char events with the previous Key event, so // the unicode can be retrieved without sending duplicate events. if (p_event.type == KeyEvent::MessageType::CHAR_EVENT_MESSAGE && key_event_pos > 0) { @@ -670,7 +672,7 @@ void OSUWP::queue_key_event(KeyEvent &p_event) { key_event_buffer[key_event_pos++] = p_event; } -void OSUWP::set_cursor_shape(CursorShape p_shape) { +void OS_UWP::set_cursor_shape(CursorShape p_shape) { ERR_FAIL_INDEX(p_shape, CURSOR_MAX); @@ -702,62 +704,62 @@ void OSUWP::set_cursor_shape(CursorShape p_shape) { cursor_shape = p_shape; } -void OSUWP::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) { +void OS_UWP::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) { // TODO } -Error OSUWP::execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id, String *r_pipe, int *r_exitcode, bool read_stderr) { +Error OS_UWP::execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id, String *r_pipe, int *r_exitcode, bool read_stderr) { return FAILED; }; -Error OSUWP::kill(const ProcessID &p_pid) { +Error OS_UWP::kill(const ProcessID &p_pid) { return FAILED; }; -Error OSUWP::set_cwd(const String &p_cwd) { +Error OS_UWP::set_cwd(const String &p_cwd) { return FAILED; } -String OSUWP::get_executable_path() const { +String OS_UWP::get_executable_path() const { return ""; } -void OSUWP::set_icon(const Ref<Image> &p_icon) { +void OS_UWP::set_icon(const Ref<Image> &p_icon) { } -bool OSUWP::has_environment(const String &p_var) const { +bool OS_UWP::has_environment(const String &p_var) const { return false; }; -String OSUWP::get_environment(const String &p_var) const { +String OS_UWP::get_environment(const String &p_var) const { return ""; }; -bool OSUWP::set_environment(const String &p_var, const String &p_value) const { +bool OS_UWP::set_environment(const String &p_var, const String &p_value) const { return false; } -String OSUWP::get_stdin_string(bool p_block) { +String OS_UWP::get_stdin_string(bool p_block) { return String(); } -void OSUWP::move_window_to_foreground() { +void OS_UWP::move_window_to_foreground() { } -Error OSUWP::shell_open(String p_uri) { +Error OS_UWP::shell_open(String p_uri) { return FAILED; } -String OSUWP::get_locale() const { +String OS_UWP::get_locale() const { #if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP // this should work on phone 8.1, but it doesn't return "en"; @@ -767,39 +769,39 @@ String OSUWP::get_locale() const { #endif } -void OSUWP::release_rendering_thread() { +void OS_UWP::release_rendering_thread() { gl_context->release_current(); } -void OSUWP::make_rendering_thread() { +void OS_UWP::make_rendering_thread() { gl_context->make_current(); } -void OSUWP::swap_buffers() { +void OS_UWP::swap_buffers() { gl_context->swap_buffers(); } -bool OSUWP::has_touchscreen_ui_hint() const { +bool OS_UWP::has_touchscreen_ui_hint() const { TouchCapabilities ^ tc = ref new TouchCapabilities(); return tc->TouchPresent != 0 || UIViewSettings::GetForCurrentView()->UserInteractionMode == UserInteractionMode::Touch; } -bool OSUWP::has_virtual_keyboard() const { +bool OS_UWP::has_virtual_keyboard() const { return UIViewSettings::GetForCurrentView()->UserInteractionMode == UserInteractionMode::Touch; } -void OSUWP::show_virtual_keyboard(const String &p_existing_text, const Rect2 &p_screen_rect) { +void OS_UWP::show_virtual_keyboard(const String &p_existing_text, const Rect2 &p_screen_rect) { InputPane ^ pane = InputPane::GetForCurrentView(); pane->TryShow(); } -void OSUWP::hide_virtual_keyboard() { +void OS_UWP::hide_virtual_keyboard() { InputPane ^ pane = InputPane::GetForCurrentView(); pane->TryHide(); @@ -818,7 +820,7 @@ static String format_error_message(DWORD id) { return msg; } -Error OSUWP::open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path) { +Error OS_UWP::open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path) { String full_path = "game/" + p_path; p_library_handle = (void *)LoadPackagedLibrary(full_path.c_str(), 0); @@ -830,14 +832,14 @@ Error OSUWP::open_dynamic_library(const String p_path, void *&p_library_handle, return OK; } -Error OSUWP::close_dynamic_library(void *p_library_handle) { +Error OS_UWP::close_dynamic_library(void *p_library_handle) { if (!FreeLibrary((HMODULE)p_library_handle)) { return FAILED; } return OK; } -Error OSUWP::get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle, bool p_optional) { +Error OS_UWP::get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle, bool p_optional) { p_symbol_handle = (void *)GetProcAddress((HMODULE)p_library_handle, p_name.utf8().get_data()); if (!p_symbol_handle) { if (!p_optional) { @@ -850,7 +852,7 @@ Error OSUWP::get_dynamic_library_symbol_handle(void *p_library_handle, const Str return OK; } -void OSUWP::run() { +void OS_UWP::run() { if (!main_loop) return; @@ -874,35 +876,35 @@ void OSUWP::run() { main_loop->finish(); } -MainLoop *OSUWP::get_main_loop() const { +MainLoop *OS_UWP::get_main_loop() const { return main_loop; } -String OSUWP::get_user_data_dir() const { +String OS_UWP::get_user_data_dir() const { Windows::Storage::StorageFolder ^ data_folder = Windows::Storage::ApplicationData::Current->LocalFolder; return String(data_folder->Path->Data()).replace("\\", "/"); } -bool OSUWP::_check_internal_feature_support(const String &p_feature) { +bool OS_UWP::_check_internal_feature_support(const String &p_feature) { return p_feature == "pc" || p_feature == "s3tc"; } -OS::PowerState OSUWP::get_power_state() { +OS::PowerState OS_UWP::get_power_state() { return power_manager->get_power_state(); } -int OSUWP::get_power_seconds_left() { +int OS_UWP::get_power_seconds_left() { return power_manager->get_power_seconds_left(); } -int OSUWP::get_power_percent_left() { +int OS_UWP::get_power_percent_left() { return power_manager->get_power_percent_left(); } -OSUWP::OSUWP() { +OS_UWP::OS_UWP() { key_event_pos = 0; force_quit = false; @@ -936,7 +938,7 @@ OSUWP::OSUWP() { _set_logger(memnew(CompositeLogger(loggers))); } -OSUWP::~OSUWP() { +OS_UWP::~OS_UWP() { #ifdef STDOUT_FILE fclose(stdo); #endif diff --git a/platform/uwp/os_uwp.h b/platform/uwp/os_uwp.h index 5475c4e60a..fd78b3cdf7 100644 --- a/platform/uwp/os_uwp.h +++ b/platform/uwp/os_uwp.h @@ -28,15 +28,15 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef OSUWP_H -#define OSUWP_H +#ifndef OS_UWP_H +#define OS_UWP_H +#include "context_egl_uwp.h" #include "core/math/transform_2d.h" #include "core/os/input.h" #include "core/os/os.h" #include "core/ustring.h" #include "drivers/xaudio2/audio_driver_xaudio2.h" -#include "gl_context_egl.h" #include "joypad_uwp.h" #include "main/input_default.h" #include "power_uwp.h" @@ -52,7 +52,7 @@ /** @author Juan Linietsky <reduzio@gmail.com> */ -class OSUWP : public OS { +class OS_UWP : public OS { public: struct KeyEvent { @@ -95,7 +95,7 @@ private: VisualServer *visual_server; int pressrc; - ContextEGL *gl_context; + ContextEGL_UWP *gl_context; Windows::UI::Core::CoreWindow ^ window; VideoMode video_mode; @@ -144,7 +144,7 @@ private: /* clang-format off */ internal: ManagedType() { alert_close_handle = false; } - property OSUWP* os; + property OS_UWP* os; /* clang-format on */ }; ManagedType ^ managed_object; @@ -262,8 +262,8 @@ public: void queue_key_event(KeyEvent &p_event); - OSUWP(); - ~OSUWP(); + OS_UWP(); + ~OS_UWP(); }; #endif diff --git a/platform/uwp/power_uwp.h b/platform/uwp/power_uwp.h index d6623f9340..cc19904a62 100644 --- a/platform/uwp/power_uwp.h +++ b/platform/uwp/power_uwp.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef PLATFORM_UWP_POWER_UWP_H_ -#define PLATFORM_UWP_POWER_UWP_H_ +#ifndef POWER_UWP_H +#define POWER_UWP_H #include "core/os/dir_access.h" #include "core/os/file_access.h" @@ -53,4 +53,4 @@ public: int get_power_percent_left(); }; -#endif /* PLATFORM_UWP_POWER_UWP_H_ */ +#endif // POWER_UWP_H diff --git a/platform/windows/SCsub b/platform/windows/SCsub index e07d373c4b..892d734734 100644 --- a/platform/windows/SCsub +++ b/platform/windows/SCsub @@ -7,13 +7,12 @@ from platform_methods import run_in_subprocess import platform_windows_builders common_win = [ - "godot_win.cpp", - "context_gl_win.cpp", - "crash_handler_win.cpp", + "godot_windows.cpp", + "context_gl_windows.cpp", + "crash_handler_windows.cpp", "os_windows.cpp", - "ctxgl_procaddr.cpp", - "key_mapping_win.cpp", - "joypad.cpp", + "key_mapping_windows.cpp", + "joypad_windows.cpp", "power_windows.cpp", "windows_terminal_logger.cpp" ] diff --git a/platform/windows/context_gl_win.cpp b/platform/windows/context_gl_windows.cpp index 9d267c699f..e715999378 100644 --- a/platform/windows/context_gl_win.cpp +++ b/platform/windows/context_gl_windows.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* context_gl_win.cpp */ +/* context_gl_windows.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -32,7 +32,7 @@ // Author: Juan Linietsky <reduzio@gmail.com>, (C) 2008 -#include "context_gl_win.h" +#include "context_gl_windows.h" #define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091 #define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092 @@ -43,32 +43,32 @@ typedef HGLRC(APIENTRY *PFNWGLCREATECONTEXTATTRIBSARBPROC)(HDC, HGLRC, const int *); -void ContextGL_Win::release_current() { +void ContextGL_Windows::release_current() { wglMakeCurrent(hDC, NULL); } -void ContextGL_Win::make_current() { +void ContextGL_Windows::make_current() { wglMakeCurrent(hDC, hRC); } -int ContextGL_Win::get_window_width() { +int ContextGL_Windows::get_window_width() { return OS::get_singleton()->get_video_mode().width; } -int ContextGL_Win::get_window_height() { +int ContextGL_Windows::get_window_height() { return OS::get_singleton()->get_video_mode().height; } -void ContextGL_Win::swap_buffers() { +void ContextGL_Windows::swap_buffers() { SwapBuffers(hDC); } -void ContextGL_Win::set_use_vsync(bool p_use) { +void ContextGL_Windows::set_use_vsync(bool p_use) { if (wglSwapIntervalEXT) { wglSwapIntervalEXT(p_use ? 1 : 0); @@ -76,14 +76,14 @@ void ContextGL_Win::set_use_vsync(bool p_use) { use_vsync = p_use; } -bool ContextGL_Win::is_using_vsync() const { +bool ContextGL_Windows::is_using_vsync() const { return use_vsync; } #define _WGL_CONTEXT_DEBUG_BIT_ARB 0x0001 -Error ContextGL_Win::initialize() { +Error ContextGL_Windows::initialize() { static PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor @@ -172,14 +172,14 @@ Error ContextGL_Win::initialize() { return OK; } -ContextGL_Win::ContextGL_Win(HWND hwnd, bool p_opengl_3_context) { +ContextGL_Windows::ContextGL_Windows(HWND hwnd, bool p_opengl_3_context) { opengl_3_context = p_opengl_3_context; hWnd = hwnd; use_vsync = false; } -ContextGL_Win::~ContextGL_Win() { +ContextGL_Windows::~ContextGL_Windows() { } #endif diff --git a/platform/windows/context_gl_win.h b/platform/windows/context_gl_windows.h index 3076bbb1e8..09801b9146 100644 --- a/platform/windows/context_gl_win.h +++ b/platform/windows/context_gl_windows.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* context_gl_win.h */ +/* context_gl_windows.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -43,7 +43,7 @@ typedef bool(APIENTRY *PFNWGLSWAPINTERVALEXTPROC)(int interval); -class ContextGL_Win : public ContextGL { +class ContextGL_Windows : public ContextGL { HDC hDC; HGLRC hRC; @@ -68,8 +68,8 @@ public: virtual void set_use_vsync(bool p_use); virtual bool is_using_vsync() const; - ContextGL_Win(HWND hwnd, bool p_opengl_3_context); - virtual ~ContextGL_Win(); + ContextGL_Windows(HWND hwnd, bool p_opengl_3_context); + virtual ~ContextGL_Windows(); }; #endif diff --git a/platform/windows/crash_handler_win.cpp b/platform/windows/crash_handler_windows.cpp index 1d93c6d8dd..4006c4c60e 100644 --- a/platform/windows/crash_handler_win.cpp +++ b/platform/windows/crash_handler_windows.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* crash_handler_win.cpp */ +/* crash_handler_windows.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,9 +28,11 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#include "crash_handler_windows.h" + +#include "core/os/os.h" #include "core/project_settings.h" #include "main/main.h" -#include "os_windows.h" #ifdef CRASH_HANDLER_EXCEPTION @@ -39,6 +41,7 @@ #include <psapi.h> #include <algorithm> #include <iterator> +#include <vector> #pragma comment(lib, "psapi.lib") #pragma comment(lib, "dbghelp.lib") diff --git a/platform/windows/crash_handler_win.h b/platform/windows/crash_handler_windows.h index 016612a00e..eba72beb7e 100644 --- a/platform/windows/crash_handler_win.h +++ b/platform/windows/crash_handler_windows.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* crash_handler_win.h */ +/* crash_handler_windows.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef CRASH_HANDLER_WIN_H -#define CRASH_HANDLER_WIN_H +#ifndef CRASH_HANDLER_WINDOWS_H +#define CRASH_HANDLER_WINDOWS_H #include <windows.h> @@ -54,4 +54,4 @@ public: ~CrashHandler(); }; -#endif +#endif // CRASH_HANDLER_WINDOWS_H diff --git a/platform/windows/ctxgl_procaddr.cpp b/platform/windows/ctxgl_procaddr.cpp deleted file mode 100644 index ecff8f7a4d..0000000000 --- a/platform/windows/ctxgl_procaddr.cpp +++ /dev/null @@ -1,188 +0,0 @@ -/*************************************************************************/ -/* ctxgl_procaddr.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifdef OPENGL_ENABLED -#include "ctxgl_procaddr.h" -#include <GL/gl.h> -#include <stdio.h> - -static PROC _gl_procs[] = { - (PROC)glCullFace, - (PROC)glFrontFace, - (PROC)glHint, - (PROC)glLineWidth, - (PROC)glPointSize, - (PROC)glPolygonMode, - (PROC)glScissor, - (PROC)glTexParameterf, - (PROC)glTexParameterfv, - (PROC)glTexParameteri, - (PROC)glTexParameteriv, - (PROC)glTexImage1D, - (PROC)glTexImage2D, - (PROC)glDrawBuffer, - (PROC)glClear, - (PROC)glClearColor, - (PROC)glClearStencil, - (PROC)glClearDepth, - (PROC)glStencilMask, - (PROC)glColorMask, - (PROC)glDepthMask, - (PROC)glDisable, - (PROC)glEnable, - (PROC)glFinish, - (PROC)glFlush, - (PROC)glBlendFunc, - (PROC)glLogicOp, - (PROC)glStencilFunc, - (PROC)glStencilOp, - (PROC)glDepthFunc, - (PROC)glPixelStoref, - (PROC)glPixelStorei, - (PROC)glReadBuffer, - (PROC)glReadPixels, - (PROC)glGetBooleanv, - (PROC)glGetDoublev, - (PROC)glGetError, - (PROC)glGetFloatv, - (PROC)glGetIntegerv, - (PROC)glGetString, - (PROC)glGetTexImage, - (PROC)glGetTexParameterfv, - (PROC)glGetTexParameteriv, - (PROC)glGetTexLevelParameterfv, - (PROC)glGetTexLevelParameteriv, - (PROC)glIsEnabled, - (PROC)glDepthRange, - (PROC)glViewport, - /* not detected in ATI */ - (PROC)glDrawArrays, - (PROC)glDrawElements, - (PROC)glGetPointerv, - (PROC)glPolygonOffset, - (PROC)glCopyTexImage1D, - (PROC)glCopyTexImage2D, - (PROC)glCopyTexSubImage1D, - (PROC)glCopyTexSubImage2D, - (PROC)glTexSubImage1D, - (PROC)glTexSubImage2D, - (PROC)glBindTexture, - (PROC)glDeleteTextures, - (PROC)glGenTextures, - (PROC)glIsTexture, - - 0 -}; - -static const char *_gl_proc_names[] = { - "glCullFace", - "glFrontFace", - "glHint", - "glLineWidth", - "glPointSize", - "glPolygonMode", - "glScissor", - "glTexParameterf", - "glTexParameterfv", - "glTexParameteri", - "glTexParameteriv", - "glTexImage1D", - "glTexImage2D", - "glDrawBuffer", - "glClear", - "glClearColor", - "glClearStencil", - "glClearDepth", - "glStencilMask", - "glColorMask", - "glDepthMask", - "glDisable", - "glEnable", - "glFinish", - "glFlush", - "glBlendFunc", - "glLogicOp", - "glStencilFunc", - "glStencilOp", - "glDepthFunc", - "glPixelStoref", - "glPixelStorei", - "glReadBuffer", - "glReadPixels", - "glGetBooleanv", - "glGetDoublev", - "glGetError", - "glGetFloatv", - "glGetIntegerv", - "glGetString", - "glGetTexImage", - "glGetTexParameterfv", - "glGetTexParameteriv", - "glGetTexLevelParameterfv", - "glGetTexLevelParameteriv", - "glIsEnabled", - "glDepthRange", - "glViewport", - /* not detected in ati */ - "glDrawArrays", - "glDrawElements", - "glGetPointerv", - "glPolygonOffset", - "glCopyTexImage1D", - "glCopyTexImage2D", - "glCopyTexSubImage1D", - "glCopyTexSubImage2D", - "glTexSubImage1D", - "glTexSubImage2D", - "glBindTexture", - "glDeleteTextures", - "glGenTextures", - "glIsTexture", - - 0 -}; - -PROC get_gl_proc_address(const char *p_address) { - - PROC proc = wglGetProcAddress((const CHAR *)p_address); - if (!proc) { - - int i = 0; - while (_gl_procs[i]) { - - if (strcmp(p_address, _gl_proc_names[i]) == 0) { - return _gl_procs[i]; - } - i++; - } - } - return proc; -} -#endif diff --git a/platform/windows/ctxgl_procaddr.h b/platform/windows/ctxgl_procaddr.h deleted file mode 100644 index cc40804ae6..0000000000 --- a/platform/windows/ctxgl_procaddr.h +++ /dev/null @@ -1,39 +0,0 @@ -/*************************************************************************/ -/* ctxgl_procaddr.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef CTXGL_PROCADDR_H -#define CTXGL_PROCADDR_H - -#ifdef OPENGL_ENABLED -#include <windows.h> - -PROC get_gl_proc_address(const char *p_address); -#endif -#endif // CTXGL_PROCADDR_H diff --git a/platform/windows/detect.py b/platform/windows/detect.py index 0662bc2edc..426a5e9e61 100644 --- a/platform/windows/detect.py +++ b/platform/windows/detect.py @@ -205,8 +205,8 @@ def configure_msvc(env, manual_msvc_config): print("Missing environment variable: WindowsSdkDir") env.AppendUnique(CPPDEFINES = ['WINDOWS_ENABLED', 'OPENGL_ENABLED', - 'RTAUDIO_ENABLED', 'WASAPI_ENABLED', - 'WINMIDI_ENABLED', 'TYPED_METHOD_BIND', + 'WASAPI_ENABLED', 'WINMIDI_ENABLED', + 'TYPED_METHOD_BIND', 'WIN32', 'MSVC', 'WINVER=%s' % env["target_win_version"], '_WIN32_WINNT=%s' % env["target_win_version"]]) @@ -326,8 +326,8 @@ def configure_mingw(env): env.Append(CCFLAGS=['-DWINDOWS_ENABLED', '-mwindows']) env.Append(CCFLAGS=['-DOPENGL_ENABLED']) - env.Append(CCFLAGS=['-DRTAUDIO_ENABLED']) env.Append(CCFLAGS=['-DWASAPI_ENABLED']) + env.Append(CCFLAGS=['-DWINMIDI_ENABLED']) env.Append(CCFLAGS=['-DWINVER=%s' % env['target_win_version'], '-D_WIN32_WINNT=%s' % env['target_win_version']]) env.Append(LIBS=['mingw32', 'opengl32', 'dsound', 'ole32', 'd3d9', 'winmm', 'gdi32', 'iphlpapi', 'shlwapi', 'wsock32', 'ws2_32', 'kernel32', 'oleaut32', 'dinput8', 'dxguid', 'ksuser', 'imm32', 'bcrypt','avrt']) @@ -347,12 +347,12 @@ def configure(env): env['ENV']['TMP'] = os.environ['TMP'] # First figure out which compiler, version, and target arch we're using - if os.getenv("VCINSTALLDIR"): + if os.getenv("VCINSTALLDIR") and not env["use_mingw"]: # Manual setup of MSVC setup_msvc_manual(env) env.msvc = True manual_msvc_config = True - elif env.get('MSVC_VERSION', ''): + elif env.get('MSVC_VERSION', '') and not env["use_mingw"]: setup_msvc_auto(env) env.msvc = True manual_msvc_config = False diff --git a/platform/windows/export/export.cpp b/platform/windows/export/export.cpp index ca2f71ca18..141ab96370 100644 --- a/platform/windows/export/export.cpp +++ b/platform/windows/export/export.cpp @@ -73,7 +73,7 @@ Error EditorExportPlatformWindows::export_project(const Ref<EditorExportPreset> } #endif - String icon_path = p_preset->get("application/icon"); + String icon_path = ProjectSettings::get_singleton()->globalize_path(p_preset->get("application/icon")); String file_verion = p_preset->get("application/file_version"); String product_version = p_preset->get("application/product_version"); String company_name = p_preset->get("application/company_name"); @@ -137,7 +137,7 @@ Error EditorExportPlatformWindows::export_project(const Ref<EditorExportPreset> void EditorExportPlatformWindows::get_export_options(List<ExportOption> *r_options) { EditorExportPlatformPC::get_export_options(r_options); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/icon", PROPERTY_HINT_GLOBAL_FILE, "*.ico"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/icon", PROPERTY_HINT_FILE, "*.ico"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/file_version"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/product_version"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/company_name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Company Name"), "")); diff --git a/platform/windows/godot_win.cpp b/platform/windows/godot_windows.cpp index 0f5065d816..0b52682c7c 100644 --- a/platform/windows/godot_win.cpp +++ b/platform/windows/godot_windows.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* godot_win.cpp */ +/* godot_windows.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -30,6 +30,7 @@ #include "main/main.h" #include "os_windows.h" + #include <locale.h> #include <stdio.h> diff --git a/platform/windows/joypad.cpp b/platform/windows/joypad_windows.cpp index 5fafc7c8c0..5a399cdf90 100644 --- a/platform/windows/joypad.cpp +++ b/platform/windows/joypad_windows.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* joypad.cpp */ +/* joypad_windows.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,7 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "joypad.h" +#include "joypad_windows.h" #include <oleauto.h> #include <wbemidl.h> diff --git a/platform/windows/joypad.h b/platform/windows/joypad_windows.h index 3a6c0cef9f..4af5d9bd6a 100644 --- a/platform/windows/joypad.h +++ b/platform/windows/joypad_windows.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* joypad.h */ +/* joypad_windows.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,10 +28,11 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef JOYPAD_H -#define JOYPAD_H +#ifndef JOYPAD_WINDOWS_H +#define JOYPAD_WINDOWS_H #include "os_windows.h" + #define DIRECTINPUT_VERSION 0x0800 #include <dinput.h> #include <xinput.h> // on unix the file is called "xinput.h", on windows I'm sure it won't mind @@ -145,4 +146,4 @@ private: XInputSetState_t xinput_set_state; }; -#endif +#endif // JOYPAD_WINDOWS_H diff --git a/platform/windows/key_mapping_win.cpp b/platform/windows/key_mapping_windows.cpp index f9b01e5532..01bbb072bb 100644 --- a/platform/windows/key_mapping_win.cpp +++ b/platform/windows/key_mapping_windows.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* key_mapping_win.cpp */ +/* key_mapping_windows.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,7 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "key_mapping_win.h" +#include "key_mapping_windows.h" #include <stdio.h> diff --git a/platform/windows/key_mapping_win.h b/platform/windows/key_mapping_windows.h index e4f8a61d04..dbb8c20f1e 100644 --- a/platform/windows/key_mapping_win.h +++ b/platform/windows/key_mapping_windows.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* key_mapping_win.h */ +/* key_mapping_windows.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -45,4 +45,4 @@ public: static unsigned int get_keysym(unsigned int p_code); }; -#endif +#endif // KEY_MAPPING_WINDOWS_H diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index 9ae1be9afd..9f15e7aad7 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -43,15 +43,16 @@ #include "drivers/windows/rw_lock_windows.h" #include "drivers/windows/semaphore_windows.h" #include "drivers/windows/thread_windows.h" -#include "joypad.h" +#include "joypad_windows.h" #include "lang_table.h" #include "main/main.h" #include "servers/audio_server.h" #include "servers/visual/visual_server_raster.h" #include "servers/visual/visual_server_wrap_mt.h" #include "windows_terminal_logger.h" -#include <avrt.h> +#include <avrt.h> +#include <direct.h> #include <process.h> #include <regstr.h> #include <shlobj.h> @@ -1273,7 +1274,7 @@ Error OS_Windows::initialize(const VideoMode &p_desired, int p_video_driver, int gl_context = NULL; while (!gl_context) { - gl_context = memnew(ContextGL_Win(hWnd, gles3_context)); + gl_context = memnew(ContextGL_Windows(hWnd, gles3_context)); if (gl_context->initialize() != OK) { memdelete(gl_context); @@ -2137,7 +2138,9 @@ OS::TimeZoneInfo OS_Windows::get_time_zone_info() const { ret.name = info.StandardName; } - ret.bias = info.Bias; + // Bias value returned by GetTimeZoneInformation is inverted of what we expect + // For example on GMT-3 GetTimeZoneInformation return a Bias of 180, so invert the value to get -180 + ret.bias = -info.Bias; return ret; } @@ -3019,9 +3022,6 @@ OS_Windows::OS_Windows(HINSTANCE _hInstance) { #ifdef WASAPI_ENABLED AudioDriverManager::add_driver(&driver_wasapi); #endif -#ifdef RTAUDIO_ENABLED - AudioDriverManager::add_driver(&driver_rtaudio); -#endif #ifdef XAUDIO2_ENABLED AudioDriverManager::add_driver(&driver_xaudio2); #endif diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h index 771789c86b..e27dbbe530 100644 --- a/platform/windows/os_windows.h +++ b/platform/windows/os_windows.h @@ -30,14 +30,17 @@ #ifndef OS_WINDOWS_H #define OS_WINDOWS_H -#include "context_gl_win.h" + +#include "context_gl_windows.h" #include "core/os/input.h" #include "core/os/os.h" #include "core/project_settings.h" -#include "crash_handler_win.h" -#include "drivers/rtaudio/audio_driver_rtaudio.h" +#include "crash_handler_windows.h" +#include "drivers/unix/ip_unix.h" #include "drivers/wasapi/audio_driver_wasapi.h" -#include "drivers/winmidi/win_midi.h" +#include "drivers/winmidi/midi_driver_winmidi.h" +#include "key_mapping_windows.h" +#include "main/input_default.h" #include "power_windows.h" #include "servers/audio_server.h" #include "servers/visual/rasterizer.h" @@ -45,9 +48,6 @@ #ifdef XAUDIO2_ENABLED #include "drivers/xaudio2/audio_driver_xaudio2.h" #endif -#include "drivers/unix/ip_unix.h" -#include "key_mapping_win.h" -#include "main/input_default.h" #include <fcntl.h> #include <io.h> @@ -86,7 +86,7 @@ class OS_Windows : public OS { int old_x, old_y; Point2i center; #if defined(OPENGL_ENABLED) - ContextGL_Win *gl_context; + ContextGL_Windows *gl_context; #endif VisualServer *visual_server; int pressrc; @@ -141,9 +141,6 @@ class OS_Windows : public OS { #ifdef WASAPI_ENABLED AudioDriverWASAPI driver_wasapi; #endif -#ifdef RTAUDIO_ENABLED - AudioDriverRtAudio driver_rtaudio; -#endif #ifdef XAUDIO2_ENABLED AudioDriverXAudio2 driver_xaudio2; #endif diff --git a/platform/windows/power_windows.h b/platform/windows/power_windows.h index 4d83d75e00..ef75ce6271 100644 --- a/platform/windows/power_windows.h +++ b/platform/windows/power_windows.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef PLATFORM_WINDOWS_POWER_WINDOWS_H_ -#define PLATFORM_WINDOWS_POWER_WINDOWS_H_ +#ifndef POWER_WINDOWS_H +#define POWER_WINDOWS_H #include "core/os/dir_access.h" #include "core/os/file_access.h" @@ -55,4 +55,4 @@ public: int get_power_percent_left(); }; -#endif /* PLATFORM_WINDOWS_POWER_WINDOWS_H_ */ +#endif // POWER_WINDOWS_H diff --git a/platform/x11/crash_handler_x11.cpp b/platform/x11/crash_handler_x11.cpp index 8737a2b92b..1e7f393bdd 100644 --- a/platform/x11/crash_handler_x11.cpp +++ b/platform/x11/crash_handler_x11.cpp @@ -28,15 +28,16 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifdef DEBUG_ENABLED -#define CRASH_HANDLER_ENABLED 1 -#endif - #include "crash_handler_x11.h" + #include "core/os/os.h" #include "core/project_settings.h" #include "main/main.h" +#ifdef DEBUG_ENABLED +#define CRASH_HANDLER_ENABLED 1 +#endif + #ifdef CRASH_HANDLER_ENABLED #include <cxxabi.h> #include <dlfcn.h> diff --git a/platform/x11/crash_handler_x11.h b/platform/x11/crash_handler_x11.h index 6efdd33d9d..d0664aef85 100644 --- a/platform/x11/crash_handler_x11.h +++ b/platform/x11/crash_handler_x11.h @@ -45,4 +45,4 @@ public: ~CrashHandler(); }; -#endif +#endif // CRASH_HANDLER_X11_H diff --git a/platform/x11/detect.py b/platform/x11/detect.py index 72139538b7..16760f9407 100644 --- a/platform/x11/detect.py +++ b/platform/x11/detect.py @@ -2,7 +2,7 @@ import os import platform import sys from compat import decode_utf8 - +from methods import get_compiler_version def is_active(): return True @@ -161,18 +161,11 @@ def configure(env): env.Append(CCFLAGS=['-pipe']) env.Append(LINKFLAGS=['-pipe']) - # Check for gcc version > 5 before adding -no-pie - import re - import subprocess - proc = subprocess.Popen([env['CXX'], '--version'], stdout=subprocess.PIPE) - (stdout, _) = proc.communicate() - stdout = decode_utf8(stdout) - match = re.search('[0-9][0-9.]*', stdout) - if match is not None: - version = match.group().split('.') - if (version[0] > '5'): - env.Append(CCFLAGS=['-fpie']) - env.Append(LINKFLAGS=['-no-pie']) + # Check for gcc version >= 6 before adding -no-pie + version = get_compiler_version(env) + if version != None and version[0] > '6': + env.Append(CCFLAGS=['-fpie']) + env.Append(LINKFLAGS=['-no-pie']) ## Dependencies diff --git a/platform/x11/joypad_linux.cpp b/platform/x11/joypad_linux.cpp index 907c652ab4..7cf0a1ef1e 100644 --- a/platform/x11/joypad_linux.cpp +++ b/platform/x11/joypad_linux.cpp @@ -476,7 +476,7 @@ void JoypadLinux::process_joypads() { // ev may be tainted and out of MAX_KEY range, which will cause // joy->key_map[ev.code] to crash - if (ev.code < 0 || ev.code >= MAX_KEY) + if (ev.code >= MAX_KEY) return; switch (ev.type) { diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp index e0924fc982..879642d8f9 100644 --- a/platform/x11/os_x11.cpp +++ b/platform/x11/os_x11.cpp @@ -243,8 +243,37 @@ Error OS_X11::initialize(const VideoMode &p_desired, int p_video_driver, int p_a // maybe contextgl wants to be in charge of creating the window #if defined(OPENGL_ENABLED) if (getenv("DRI_PRIME") == NULL) { - print_verbose("Detecting GPUs, set DRI_PRIME in the environment to override GPU detection logic."); - int use_prime = detect_prime(); + int use_prime = -1; + + if (getenv("PRIMUS_DISPLAY") || + getenv("PRIMUS_libGLd") || + getenv("PRIMUS_libGLa") || + getenv("PRIMUS_libGL") || + getenv("PRIMUS_LOAD_GLOBAL") || + getenv("BUMBLEBEE_SOCKET")) { + + print_verbose("Optirun/primusrun detected. Skipping GPU detection"); + use_prime = 0; + } + + if (getenv("LD_LIBRARY_PATH")) { + String ld_library_path(getenv("LD_LIBRARY_PATH")); + Vector<String> libraries = ld_library_path.split(":"); + + for (int i = 0; i < libraries.size(); ++i) { + if (FileAccess::exists(libraries[i] + "/libGL.so.1") || + FileAccess::exists(libraries[i] + "/libGL.so")) { + + print_verbose("Custom libGL override detected. Skipping GPU detection"); + use_prime = 0; + } + } + } + + if (use_prime == -1) { + print_verbose("Detecting GPUs, set DRI_PRIME in the environment to override GPU detection logic."); + use_prime = detect_prime(); + } if (use_prime) { print_line("Found discrete GPU, setting DRI_PRIME=1 to use it."); @@ -1714,7 +1743,7 @@ void OS_X11::handle_key_event(XKeyEvent *p_event, bool p_echo) { // is correct, but the xorg developers are // not very helpful today. - ::Time tresh = ABS(peek_event.xkey.time - xkeyevent->time); + ::Time tresh = ABSDIFF(peek_event.xkey.time, xkeyevent->time); if (peek_event.type == KeyPress && tresh < 5) { KeySym rk; XLookupString((XKeyEvent *)&peek_event, str, 256, &rk, NULL); @@ -3004,7 +3033,9 @@ bool OS_X11::is_vsync_enabled() const { */ void OS_X11::set_context(int p_context) { + char *config_name = NULL; XClassHint *classHint = XAllocClassHint(); + if (classHint) { char *wm_class = (char *)"Godot"; @@ -3015,13 +3046,20 @@ void OS_X11::set_context(int p_context) { if (p_context == CONTEXT_ENGINE) { classHint->res_name = (char *)"Godot_Engine"; - wm_class = (char *)((String)GLOBAL_GET("application/config/name")).utf8().ptrw(); + char *config_name_tmp = (char *)((String)GLOBAL_GET("application/config/name")).utf8().ptrw(); + if (config_name_tmp) + config_name = strdup(config_name_tmp); + else + config_name = strdup("Godot Engine"); + + wm_class = config_name; } classHint->res_class = wm_class; XSetClassHint(x11_display, x11_window, classHint); XFree(classHint); + free(config_name); } } diff --git a/platform/x11/os_x11.h b/platform/x11/os_x11.h index cf1619bae2..6d1a66af84 100644 --- a/platform/x11/os_x11.h +++ b/platform/x11/os_x11.h @@ -35,7 +35,7 @@ #include "core/os/input.h" #include "crash_handler_x11.h" #include "drivers/alsa/audio_driver_alsa.h" -#include "drivers/alsamidi/alsa_midi.h" +#include "drivers/alsamidi/midi_driver_alsamidi.h" #include "drivers/pulseaudio/audio_driver_pulseaudio.h" #include "drivers/unix/os_unix.h" #include "joypad_linux.h" diff --git a/platform/x11/power_x11.h b/platform/x11/power_x11.h index 56fbd602f4..469e3910f4 100644 --- a/platform/x11/power_x11.h +++ b/platform/x11/power_x11.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef X11_POWER_H_ -#define X11_POWER_H_ +#ifndef POWER_X11_H +#define POWER_X11_H #include "core/os/dir_access.h" #include "core/os/file_access.h" @@ -63,4 +63,4 @@ public: int get_power_percent_left(); }; -#endif /* X11_POWER_H_ */ +#endif // POWER_X11_H diff --git a/scene/2d/animated_sprite.cpp b/scene/2d/animated_sprite.cpp index 28ddf6b5f8..3d7ff5f1fd 100644 --- a/scene/2d/animated_sprite.cpp +++ b/scene/2d/animated_sprite.cpp @@ -276,9 +276,9 @@ void SpriteFrames::_set_animations(const Array &p_animations) { anim.speed = d["speed"]; anim.loop = d["loop"]; Array frames = d["frames"]; - for (int i = 0; i < frames.size(); i++) { + for (int j = 0; j < frames.size(); j++) { - RES res = frames[i]; + RES res = frames[j]; anim.frames.push_back(res); } diff --git a/scene/2d/area_2d.cpp b/scene/2d/area_2d.cpp index 63c4758a34..9e8bf62fc5 100644 --- a/scene/2d/area_2d.cpp +++ b/scene/2d/area_2d.cpp @@ -426,7 +426,7 @@ bool Area2D::is_monitoring() const { void Area2D::set_monitorable(bool p_enable) { - if (locked || Physics2DServer::get_singleton()->is_flushing_queries()) { + if (locked || (is_inside_tree() && Physics2DServer::get_singleton()->is_flushing_queries())) { ERR_EXPLAIN("Function blocked during in/out signal. Use set_deferred(\"monitorable\",true/false)"); } ERR_FAIL_COND(locked || Physics2DServer::get_singleton()->is_flushing_queries()); diff --git a/scene/2d/audio_stream_player_2d.cpp b/scene/2d/audio_stream_player_2d.cpp index 961d2b00ef..7b28ad2c12 100644 --- a/scene/2d/audio_stream_player_2d.cpp +++ b/scene/2d/audio_stream_player_2d.cpp @@ -37,7 +37,7 @@ void AudioStreamPlayer2D::_mix_audio() { if (!stream_playback.is_valid() || !active || - (stream_paused && !stream_paused_fade_out)) { + (stream_paused && !stream_fade_out)) { return; } @@ -50,7 +50,7 @@ void AudioStreamPlayer2D::_mix_audio() { AudioFrame *buffer = mix_buffer.ptrw(); int buffer_size = mix_buffer.size(); - if (stream_paused_fade_out) { + if (stream_fade_out) { // Short fadeout ramp buffer_size = MIN(buffer_size, 128); } @@ -84,10 +84,10 @@ void AudioStreamPlayer2D::_mix_audio() { } //mix! - AudioFrame target_volume = stream_paused_fade_out ? AudioFrame(0.f, 0.f) : current.vol; - AudioFrame vol_prev = stream_paused_fade_in ? AudioFrame(0.f, 0.f) : prev_outputs[i].vol; + AudioFrame target_volume = stream_fade_out ? AudioFrame(0.f, 0.f) : current.vol; + AudioFrame vol_prev = stream_fade_in ? AudioFrame(0.f, 0.f) : prev_outputs[i].vol; AudioFrame vol_inc = (target_volume - vol_prev) / float(buffer_size); - AudioFrame vol = stream_paused_fade_in ? AudioFrame(0.f, 0.f) : current.vol; + AudioFrame vol = stream_fade_in ? AudioFrame(0.f, 0.f) : current.vol; int cc = AudioServer::get_singleton()->get_channel_count(); @@ -139,9 +139,15 @@ void AudioStreamPlayer2D::_mix_audio() { active = false; } + if (stream_stop) { + active = false; + set_physics_process_internal(false); + setplay = -1; + } + output_ready = false; - stream_paused_fade_in = false; - stream_paused_fade_out = false; + stream_fade_in = false; + stream_fade_out = false; } void AudioStreamPlayer2D::_notification(int p_what) { @@ -323,6 +329,7 @@ void AudioStreamPlayer2D::play(float p_from_pos) { } if (stream_playback.is_valid()) { + stream_stop = false; active = true; setplay = p_from_pos; output_ready = false; @@ -340,9 +347,8 @@ void AudioStreamPlayer2D::seek(float p_seconds) { void AudioStreamPlayer2D::stop() { if (stream_playback.is_valid()) { - active = false; - set_physics_process_internal(false); - setplay = -1; + stream_stop = true; + stream_fade_out = true; } } @@ -457,8 +463,8 @@ void AudioStreamPlayer2D::set_stream_paused(bool p_pause) { if (p_pause != stream_paused) { stream_paused = p_pause; - stream_paused_fade_in = p_pause ? false : true; - stream_paused_fade_out = p_pause ? true : false; + stream_fade_in = p_pause ? false : true; + stream_fade_out = p_pause ? true : false; } } @@ -537,8 +543,9 @@ AudioStreamPlayer2D::AudioStreamPlayer2D() { output_ready = false; area_mask = 1; stream_paused = false; - stream_paused_fade_in = false; - stream_paused_fade_out = false; + stream_fade_in = false; + stream_fade_out = false; + stream_stop = false; AudioServer::get_singleton()->connect("bus_layout_changed", this, "_bus_layout_changed"); } diff --git a/scene/2d/audio_stream_player_2d.h b/scene/2d/audio_stream_player_2d.h index cc00b59010..caf5c6ee49 100644 --- a/scene/2d/audio_stream_player_2d.h +++ b/scene/2d/audio_stream_player_2d.h @@ -73,8 +73,9 @@ private: float pitch_scale; bool autoplay; bool stream_paused; - bool stream_paused_fade_in; - bool stream_paused_fade_out; + bool stream_fade_in; + bool stream_fade_out; + bool stream_stop; StringName bus; void _mix_audio(); diff --git a/scene/2d/canvas_item.cpp b/scene/2d/canvas_item.cpp index 41cee7335e..2739f71543 100644 --- a/scene/2d/canvas_item.cpp +++ b/scene/2d/canvas_item.cpp @@ -131,19 +131,15 @@ void CanvasItemMaterial::_update_shader() { code += "\tVERTEX.xy /= vec2(h_frames, v_frames);\n"; - code += "\tint total_frames = particles_anim_h_frames * particles_anim_v_frames;\n"; - code += "\tint frame = int(float(total_frames) * INSTANCE_CUSTOM.z);\n"; - code += "\tif (particles_anim_loop) {\n"; - code += "\t\tframe = int(abs(frame) % total_frames);\n"; + code += "\tfloat particle_total_frames = float(particles_anim_h_frames * particles_anim_v_frames);\n"; + code += "\tfloat particle_frame = floor(INSTANCE_CUSTOM.z * float(particle_total_frames));\n"; + code += "\tif (!particles_anim_loop) {\n"; + code += "\t\tparticle_frame = clamp(particle_frame, 0.0, particle_total_frames - 1.0);\n"; code += "\t} else {\n"; - code += "\t\tframe = clamp(frame, 0, total_frames - 1);\n"; - code += "\t}\n"; - - code += "\tfloat frame_w = 1.0 / h_frames;\n"; - code += "\tfloat frame_h = 1.0 / v_frames;\n"; - code += "\tUV.x = UV.x * frame_w + frame_w * float(frame % particles_anim_h_frames);\n"; - code += "\tUV.y = UV.y * frame_h + frame_h * float(frame / particles_anim_h_frames);\n"; - + code += "\t\tparticle_frame = mod(particle_frame, particle_total_frames);\n"; + code += "\t}"; + code += "\tUV /= vec2(h_frames, v_frames);\n"; + code += "\tUV += vec2(mod(particle_frame, h_frames) / h_frames, floor(particle_frame / h_frames) / v_frames);\n"; code += "}\n"; } diff --git a/scene/2d/collision_shape_2d.cpp b/scene/2d/collision_shape_2d.cpp index c756f49bbd..5440a1d8c3 100644 --- a/scene/2d/collision_shape_2d.cpp +++ b/scene/2d/collision_shape_2d.cpp @@ -36,9 +36,9 @@ #include "scene/resources/circle_shape_2d.h" #include "scene/resources/concave_polygon_shape_2d.h" #include "scene/resources/convex_polygon_shape_2d.h" +#include "scene/resources/line_shape_2d.h" #include "scene/resources/rectangle_shape_2d.h" #include "scene/resources/segment_shape_2d.h" -#include "scene/resources/shape_line_2d.h" void CollisionShape2D::_shape_changed() { diff --git a/scene/2d/cpu_particles_2d.cpp b/scene/2d/cpu_particles_2d.cpp index 21feb6e226..c50a8d4a1a 100644 --- a/scene/2d/cpu_particles_2d.cpp +++ b/scene/2d/cpu_particles_2d.cpp @@ -594,7 +594,7 @@ void CPUParticles2D::_particles_process(float p_delta) { if (restart_time >= prev_time) { restart = true; if (fractional_delta) { - local_delta = (1.0 - restart_time + time) * lifetime; + local_delta = (lifetime - restart_time + time) * lifetime; } } else if (restart_time < time) { @@ -1189,7 +1189,7 @@ void CPUParticles2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emitting"), "set_emitting", "is_emitting"); ADD_PROPERTY(PropertyInfo(Variant::INT, "amount", PROPERTY_HINT_EXP_RANGE, "1,1000000,1"), "set_amount", "get_amount"); ADD_GROUP("Time", ""); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "lifetime", PROPERTY_HINT_EXP_RANGE, "0.01,600.0,0.01"), "set_lifetime", "get_lifetime"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "lifetime", PROPERTY_HINT_EXP_RANGE, "0.01,600.0,0.01,or_greater"), "set_lifetime", "get_lifetime"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "one_shot"), "set_one_shot", "get_one_shot"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "preprocess", PROPERTY_HINT_EXP_RANGE, "0.00,600.0,0.01"), "set_pre_process_time", "get_pre_process_time"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "speed_scale", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_speed_scale", "get_speed_scale"); diff --git a/scene/2d/line_builder.h b/scene/2d/line_builder.h index 2ca28d09c4..b961385e33 100644 --- a/scene/2d/line_builder.h +++ b/scene/2d/line_builder.h @@ -34,7 +34,7 @@ #include "core/color.h" #include "core/math/vector2.h" #include "line_2d.h" -#include "scene/resources/color_ramp.h" +#include "scene/resources/gradient.h" class LineBuilder { public: diff --git a/scene/2d/navigation2d.cpp b/scene/2d/navigation_2d.cpp index 1c0e924433..57e0a5b118 100644 --- a/scene/2d/navigation2d.cpp +++ b/scene/2d/navigation_2d.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* navigation2d.cpp */ +/* navigation_2d.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,7 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "navigation2d.h" +#include "navigation_2d.h" #define USE_ENTRY_POINT diff --git a/scene/2d/navigation2d.h b/scene/2d/navigation_2d.h index fc1762221c..b4d659ff5c 100644 --- a/scene/2d/navigation2d.h +++ b/scene/2d/navigation_2d.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* navigation2d.h */ +/* navigation_2d.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -171,4 +171,4 @@ public: Navigation2D(); }; -#endif // Navigation2D2D_H +#endif // NAVIGATION_2D_H diff --git a/scene/2d/navigation_polygon.cpp b/scene/2d/navigation_polygon.cpp index 50618c6baa..0f6af358bd 100644 --- a/scene/2d/navigation_polygon.cpp +++ b/scene/2d/navigation_polygon.cpp @@ -32,7 +32,7 @@ #include "core/core_string_names.h" #include "core/engine.h" -#include "navigation2d.h" +#include "navigation_2d.h" #include "thirdparty/misc/triangulator.h" diff --git a/scene/2d/node_2d.cpp b/scene/2d/node_2d.cpp index 9a94092840..f4430d93f6 100644 --- a/scene/2d/node_2d.cpp +++ b/scene/2d/node_2d.cpp @@ -376,7 +376,7 @@ void Node2D::look_at(const Vector2 &p_pos) { float Node2D::get_angle_to(const Vector2 &p_pos) const { - return (get_global_transform().affine_inverse().xform(p_pos)).angle(); + return (to_local(p_pos) * get_scale()).angle(); } Point2 Node2D::to_local(Point2 p_global) const { diff --git a/scene/2d/particles_2d.cpp b/scene/2d/particles_2d.cpp index c005c33a19..9701998f5d 100644 --- a/scene/2d/particles_2d.cpp +++ b/scene/2d/particles_2d.cpp @@ -30,6 +30,7 @@ #include "particles_2d.h" +#include "core/os/os.h" #include "scene/resources/particles_material.h" #include "scene/scene_string_names.h" @@ -213,6 +214,10 @@ bool Particles2D::get_fractional_delta() const { String Particles2D::get_configuration_warning() const { + if (OS::get_singleton()->get_current_video_driver() == OS::VIDEO_DRIVER_GLES2) { + return TTR("GPU-based particles are not supported by the GLES2 video driver.\nUse the CPUParticles2D node instead. You can use the \"Convert to CPUParticles\" option for this purpose."); + } + String warnings; if (process_material.is_null()) { diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index f4bc8ad6b9..ce80bc508e 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -1290,7 +1290,7 @@ Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const floor_velocity = collision.collider_vel; if (p_stop_on_slope) { - if (Vector2() == lv_n + p_floor_direction && collision.travel.length() < 1) { + if ((lv_n + p_floor_direction).length() < 0.01 && collision.travel.length() < 1) { Transform2D gt = get_global_transform(); gt.elements[2] -= collision.travel.project(p_floor_direction.tangent()); set_global_transform(gt); @@ -1309,9 +1309,6 @@ Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const motion = motion.slide(n); lv = lv.slide(n); } - - if (p_stop_on_slope) - break; } if (!found_collision) { @@ -1338,13 +1335,21 @@ Vector2 KinematicBody2D::move_and_slide_with_snap(const Vector2 &p_linear_veloci Transform2D gt = get_global_transform(); if (move_and_collide(p_snap, p_infinite_inertia, col, false, true)) { - gt.elements[2] += col.travel; - if (p_floor_direction != Vector2() && Math::acos(p_floor_direction.normalized().dot(col.normal)) < p_floor_max_angle) { - on_floor = true; - on_floor_body = col.collider_rid; - floor_velocity = col.collider_vel; + bool apply = true; + if (p_floor_direction != Vector2()) { + if (Math::acos(p_floor_direction.normalized().dot(col.normal)) < p_floor_max_angle) { + on_floor = true; + on_floor_body = col.collider_rid; + floor_velocity = col.collider_vel; + } else { + apply = false; + } + } + + if (apply) { + gt.elements[2] += col.travel; + set_global_transform(gt); } - set_global_transform(gt); } return ret; diff --git a/scene/2d/polygon_2d.cpp b/scene/2d/polygon_2d.cpp index 54b304f851..1c58073f1d 100644 --- a/scene/2d/polygon_2d.cpp +++ b/scene/2d/polygon_2d.cpp @@ -88,6 +88,10 @@ bool Polygon2D::_edit_is_selected_on_click(const Point2 &p_point, double p_toler return Geometry::is_point_in_polygon(p_point - get_offset(), polygon2d); } +void Polygon2D::_skeleton_bone_setup_changed() { + update(); +} + void Polygon2D::_notification(int p_what) { switch (p_what) { @@ -102,10 +106,27 @@ void Polygon2D::_notification(int p_what) { skeleton_node = Object::cast_to<Skeleton2D>(get_node(skeleton)); } - if (skeleton_node) + ObjectID new_skeleton_id = 0; + + if (skeleton_node) { VS::get_singleton()->canvas_item_attach_skeleton(get_canvas_item(), skeleton_node->get_skeleton()); - else + new_skeleton_id = skeleton_node->get_instance_id(); + } else { VS::get_singleton()->canvas_item_attach_skeleton(get_canvas_item(), RID()); + } + + if (new_skeleton_id != current_skeleton_id) { + Object *old_skeleton = ObjectDB::get_instance(current_skeleton_id); + if (old_skeleton) { + old_skeleton->disconnect("bone_setup_changed", this, "_skeleton_bone_setup_changed"); + } + + if (skeleton_node) { + skeleton_node->connect("bone_setup_changed", this, "_skeleton_bone_setup_changed"); + } + + current_skeleton_id = new_skeleton_id; + } Vector<Vector2> points; Vector<Vector2> uvs; @@ -809,6 +830,8 @@ void Polygon2D::_bind_methods() { ClassDB::bind_method(D_METHOD("_set_bones", "bones"), &Polygon2D::_set_bones); ClassDB::bind_method(D_METHOD("_get_bones"), &Polygon2D::_get_bones); + ClassDB::bind_method(D_METHOD("_skeleton_bone_setup_changed"), &Polygon2D::_skeleton_bone_setup_changed); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "color"), "set_color", "get_color"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "offset"), "set_offset", "get_offset"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "antialiased"), "set_antialiased", "get_antialiased"); @@ -846,4 +869,5 @@ Polygon2D::Polygon2D() { color = Color(1, 1, 1); rect_cache_dirty = true; internal_vertices = 0; + current_skeleton_id = 0; } diff --git a/scene/2d/polygon_2d.h b/scene/2d/polygon_2d.h index c1d6ebe46e..f25b3885b0 100644 --- a/scene/2d/polygon_2d.h +++ b/scene/2d/polygon_2d.h @@ -65,10 +65,13 @@ class Polygon2D : public Node2D { mutable Rect2 item_rect; NodePath skeleton; + ObjectID current_skeleton_id; Array _get_bones() const; void _set_bones(const Array &p_bones); + void _skeleton_bone_setup_changed(); + protected: void _notification(int p_what); static void _bind_methods(); diff --git a/scene/2d/skeleton_2d.cpp b/scene/2d/skeleton_2d.cpp index 2a674e64e6..aa15255384 100644 --- a/scene/2d/skeleton_2d.cpp +++ b/scene/2d/skeleton_2d.cpp @@ -203,6 +203,7 @@ void Skeleton2D::_update_bone_setup() { transform_dirty = true; _update_transform(); + emit_signal("bone_setup_changed"); } void Skeleton2D::_make_transform_dirty() { @@ -291,6 +292,8 @@ void Skeleton2D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_bone", "idx"), &Skeleton2D::get_bone); ClassDB::bind_method(D_METHOD("get_skeleton"), &Skeleton2D::get_skeleton); + + ADD_SIGNAL(MethodInfo("bone_setup_changed")); } Skeleton2D::Skeleton2D() { diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp index 44730062c4..91e4f061cb 100644 --- a/scene/2d/tile_map.cpp +++ b/scene/2d/tile_map.cpp @@ -75,15 +75,15 @@ void TileMap::_notification(int p_what) { Quadrant &q = E->get(); if (navigation) { - for (Map<PosKey, Quadrant::NavPoly>::Element *E = q.navpoly_ids.front(); E; E = E->next()) { + for (Map<PosKey, Quadrant::NavPoly>::Element *F = q.navpoly_ids.front(); F; F = F->next()) { - navigation->navpoly_remove(E->get().id); + navigation->navpoly_remove(F->get().id); } q.navpoly_ids.clear(); } - for (Map<PosKey, Quadrant::Occluder>::Element *E = q.occluder_instances.front(); E; E = E->next()) { - VS::get_singleton()->free(E->get().id); + for (Map<PosKey, Quadrant::Occluder>::Element *F = q.occluder_instances.front(); F; F = F->next()) { + VS::get_singleton()->free(F->get().id); } q.occluder_instances.clear(); } @@ -129,14 +129,14 @@ void TileMap::_update_quadrant_transform() { Physics2DServer::get_singleton()->body_set_state(q.body, Physics2DServer::BODY_STATE_TRANSFORM, xform); if (navigation) { - for (Map<PosKey, Quadrant::NavPoly>::Element *E = q.navpoly_ids.front(); E; E = E->next()) { + for (Map<PosKey, Quadrant::NavPoly>::Element *F = q.navpoly_ids.front(); F; F = F->next()) { - navigation->navpoly_set_transform(E->get().id, nav_rel * E->get().xform); + navigation->navpoly_set_transform(F->get().id, nav_rel * F->get().xform); } } - for (Map<PosKey, Quadrant::Occluder>::Element *E = q.occluder_instances.front(); E; E = E->next()) { - VS::get_singleton()->canvas_light_occluder_set_transform(E->get().id, global_transform * E->get().xform); + for (Map<PosKey, Quadrant::Occluder>::Element *F = q.occluder_instances.front(); F; F = F->next()) { + VS::get_singleton()->canvas_light_occluder_set_transform(F->get().id, global_transform * F->get().xform); } } } @@ -462,18 +462,18 @@ void TileMap::update_dirty_quadrants() { Vector<TileSet::ShapeData> shapes = tile_set->tile_get_shapes(c.id); - for (int i = 0; i < shapes.size(); i++) { - Ref<Shape2D> shape = shapes[i].shape; + for (int j = 0; j < shapes.size(); j++) { + Ref<Shape2D> shape = shapes[j].shape; if (shape.is_valid()) { - if (tile_set->tile_get_tile_mode(c.id) == TileSet::SINGLE_TILE || (shapes[i].autotile_coord.x == c.autotile_coord_x && shapes[i].autotile_coord.y == c.autotile_coord_y)) { + if (tile_set->tile_get_tile_mode(c.id) == TileSet::SINGLE_TILE || (shapes[j].autotile_coord.x == c.autotile_coord_x && shapes[j].autotile_coord.y == c.autotile_coord_y)) { Transform2D xform; xform.set_origin(offset.floor()); - Vector2 shape_ofs = shapes[i].shape_transform.get_origin(); + Vector2 shape_ofs = shapes[j].shape_transform.get_origin(); _fix_cell_transform(xform, c, shape_ofs + center_ofs, s); - xform *= shapes[i].shape_transform.untranslated(); + xform *= shapes[j].shape_transform.untranslated(); if (debug_canvas_item.is_valid()) { vs->canvas_item_add_set_transform(debug_canvas_item, xform); @@ -481,7 +481,7 @@ void TileMap::update_dirty_quadrants() { } ps->body_add_shape(q.body, shape->get_rid(), xform); ps->body_set_shape_metadata(q.body, shape_idx, Vector2(E->key().x, E->key().y)); - ps->body_set_shape_as_one_way_collision(q.body, shape_idx, shapes[i].one_way_collision, shapes[i].one_way_collision_margin); + ps->body_set_shape_as_one_way_collision(q.body, shape_idx, shapes[j].one_way_collision, shapes[j].one_way_collision_margin); shape_idx++; } } @@ -531,23 +531,23 @@ void TileMap::update_dirty_quadrants() { colors.resize(vsize); { PoolVector<Vector2>::Read vr = navigation_polygon_vertices.read(); - for (int i = 0; i < vsize; i++) { - vertices.write[i] = vr[i]; - colors.write[i] = debug_navigation_color; + for (int j = 0; j < vsize; j++) { + vertices.write[j] = vr[j]; + colors.write[j] = debug_navigation_color; } } Vector<int> indices; - for (int i = 0; i < navpoly->get_polygon_count(); i++) { - Vector<int> polygon = navpoly->get_polygon(i); + for (int j = 0; j < navpoly->get_polygon_count(); j++) { + Vector<int> polygon = navpoly->get_polygon(j); - for (int j = 2; j < polygon.size(); j++) { + for (int k = 2; k < polygon.size(); k++) { - int kofs[3] = { 0, j - 1, j }; - for (int k = 0; k < 3; k++) { + int kofs[3] = { 0, k - 1, k }; + for (int l = 0; l < 3; l++) { - int idx = polygon[kofs[k]]; + int idx = polygon[kofs[l]]; ERR_FAIL_INDEX(idx, vsize); indices.push_back(idx); } @@ -601,9 +601,9 @@ void TileMap::update_dirty_quadrants() { for (Map<PosKey, Quadrant>::Element *E = quadrant_map.front(); E; E = E->next()) { Quadrant &q = E->get(); - for (List<RID>::Element *E = q.canvas_items.front(); E; E = E->next()) { + for (List<RID>::Element *F = q.canvas_items.front(); F; F = F->next()) { - VS::get_singleton()->canvas_item_set_draw_index(E->get(), index++); + VS::get_singleton()->canvas_item_set_draw_index(F->get(), index++); } } @@ -1053,9 +1053,9 @@ void TileMap::_update_all_items_material_state() { for (Map<PosKey, Quadrant>::Element *E = quadrant_map.front(); E; E = E->next()) { Quadrant &q = E->get(); - for (List<RID>::Element *E = q.canvas_items.front(); E; E = E->next()) { + for (List<RID>::Element *F = q.canvas_items.front(); F; F = F->next()) { - _update_item_material_state(E->get()); + _update_item_material_state(F->get()); } } } @@ -1453,7 +1453,7 @@ Vector2 TileMap::world_to_map(const Vector2 &p_pos) const { } // Account for precision errors on the border (GH-23250). - // 0.00005 is 5*CMP_EPSILON, results would start being unpredictible if + // 0.00005 is 5*CMP_EPSILON, results would start being unpredictable if // cell size is > 15,000, but we can hardly have more precision anyway with // floating point. ret += Vector2(0.00005, 0.00005); diff --git a/scene/2d/tile_map.h b/scene/2d/tile_map.h index a44098fd77..e450e1e256 100644 --- a/scene/2d/tile_map.h +++ b/scene/2d/tile_map.h @@ -33,7 +33,7 @@ #include "core/self_list.h" #include "core/vset.h" -#include "scene/2d/navigation2d.h" +#include "scene/2d/navigation_2d.h" #include "scene/2d/node_2d.h" #include "scene/resources/tile_set.h" diff --git a/scene/2d/screen_button.cpp b/scene/2d/touch_screen_button.cpp index fb1558a404..9a1a759e72 100644 --- a/scene/2d/screen_button.cpp +++ b/scene/2d/touch_screen_button.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* screen_button.cpp */ +/* touch_screen_button.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,7 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "screen_button.h" +#include "touch_screen_button.h" + #include "core/input_map.h" #include "core/os/input.h" #include "core/os/os.h" diff --git a/scene/2d/screen_button.h b/scene/2d/touch_screen_button.h index fd944ead64..df54e5340b 100644 --- a/scene/2d/screen_button.h +++ b/scene/2d/touch_screen_button.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* screen_button.h */ +/* touch_screen_button.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,11 +28,11 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef SCREEN_BUTTON_H -#define SCREEN_BUTTON_H +#ifndef TOUCH_SCREEN_BUTTON_H +#define TOUCH_SCREEN_BUTTON_H #include "scene/2d/node_2d.h" -#include "scene/resources/bit_mask.h" +#include "scene/resources/bit_map.h" #include "scene/resources/rectangle_shape_2d.h" #include "scene/resources/texture.h" @@ -112,4 +112,4 @@ public: VARIANT_ENUM_CAST(TouchScreenButton::VisibilityMode); -#endif // SCREEN_BUTTON_H +#endif // TOUCH_SCREEN_BUTTON_H diff --git a/scene/3d/SCsub b/scene/3d/SCsub index 35cc7479d8..200cf4316f 100644 --- a/scene/3d/SCsub +++ b/scene/3d/SCsub @@ -7,6 +7,6 @@ if env['disable_3d']: env.scene_sources.append("3d/skeleton.cpp") env.scene_sources.append("3d/particles.cpp") env.scene_sources.append("3d/visual_instance.cpp") - env.scene_sources.append("3d/scenario_fx.cpp") + env.scene_sources.append("3d/world_environment.cpp") else: env.add_source_files(env.scene_sources, "*.cpp") diff --git a/scene/3d/area.cpp b/scene/3d/area.cpp index 99f43b1242..9e15a416b2 100644 --- a/scene/3d/area.cpp +++ b/scene/3d/area.cpp @@ -439,7 +439,7 @@ Array Area::get_overlapping_bodies() const { void Area::set_monitorable(bool p_enable) { - if (locked || PhysicsServer::get_singleton()->is_flushing_queries()) { + if (locked || (is_inside_tree() && PhysicsServer::get_singleton()->is_flushing_queries())) { ERR_EXPLAIN("Function blocked during in/out signal. Use set_deferred(\"monitorable\",true/false)"); } ERR_FAIL_COND(locked || PhysicsServer::get_singleton()->is_flushing_queries()); diff --git a/scene/3d/audio_stream_player_3d.cpp b/scene/3d/audio_stream_player_3d.cpp index 0f4d0383a4..cf48a2503c 100644 --- a/scene/3d/audio_stream_player_3d.cpp +++ b/scene/3d/audio_stream_player_3d.cpp @@ -32,12 +32,13 @@ #include "core/engine.h" #include "scene/3d/area.h" #include "scene/3d/camera.h" +#include "scene/3d/listener.h" #include "scene/main/viewport.h" void AudioStreamPlayer3D::_mix_audio() { if (!stream_playback.is_valid() || !active || - (stream_paused && !stream_paused_fade_out)) { + (stream_paused && !stream_fade_out)) { return; } @@ -52,7 +53,7 @@ void AudioStreamPlayer3D::_mix_audio() { AudioFrame *buffer = mix_buffer.ptrw(); int buffer_size = mix_buffer.size(); - if (stream_paused_fade_out) { + if (stream_fade_out) { // Short fadeout ramp buffer_size = MIN(buffer_size, 128); } @@ -108,10 +109,10 @@ void AudioStreamPlayer3D::_mix_audio() { int buffers = AudioServer::get_singleton()->get_channel_count(); for (int k = 0; k < buffers; k++) { - AudioFrame target_volume = stream_paused_fade_out ? AudioFrame(0.f, 0.f) : current.vol[k]; - AudioFrame vol_prev = stream_paused_fade_in ? AudioFrame(0.f, 0.f) : prev_outputs[i].vol[k]; + AudioFrame target_volume = stream_fade_out ? AudioFrame(0.f, 0.f) : current.vol[k]; + AudioFrame vol_prev = stream_fade_in ? AudioFrame(0.f, 0.f) : prev_outputs[i].vol[k]; AudioFrame vol_inc = (target_volume - vol_prev) / float(buffer_size); - AudioFrame vol = stream_paused_fade_in ? AudioFrame(0.f, 0.f) : current.vol[k]; + AudioFrame vol = stream_fade_in ? AudioFrame(0.f, 0.f) : current.vol[k]; if (!AudioServer::get_singleton()->thread_has_channel_mix_buffer(current.bus_index, k)) continue; //may have been deleted, will be updated on process @@ -197,9 +198,15 @@ void AudioStreamPlayer3D::_mix_audio() { active = false; } + if (stream_stop) { + active = false; + set_physics_process_internal(false); + setplay = -1; + } + output_ready = false; - stream_paused_fade_in = false; - stream_paused_fade_out = false; + stream_fade_in = false; + stream_fade_out = false; } float AudioStreamPlayer3D::_get_attenuation_db(float p_distance) const { @@ -324,16 +331,25 @@ void AudioStreamPlayer3D::_notification(int p_what) { if (!vp->is_audio_listener()) continue; - Vector3 local_pos = camera->get_global_transform().orthonormalized().affine_inverse().xform(global_pos); + bool listener_is_camera = true; + Spatial *listener_node = camera; + + Listener *listener = vp->get_listener(); + if (listener) { + listener_node = listener; + listener_is_camera = false; + } + + Vector3 local_pos = listener_node->get_global_transform().orthonormalized().affine_inverse().xform(global_pos); float dist = local_pos.length(); Vector3 area_sound_pos; - Vector3 cam_area_pos; + Vector3 listener_area_pos; if (area && area->is_using_reverb_bus() && area->get_reverb_uniformity() > 0) { - area_sound_pos = space_state->get_closest_point_to_object_volume(area->get_rid(), camera->get_global_transform().origin); - cam_area_pos = camera->get_global_transform().affine_inverse().xform(area_sound_pos); + area_sound_pos = space_state->get_closest_point_to_object_volume(area->get_rid(), listener_node->get_global_transform().origin); + listener_area_pos = listener_node->get_global_transform().affine_inverse().xform(area_sound_pos); } if (max_distance > 0) { @@ -341,10 +357,10 @@ void AudioStreamPlayer3D::_notification(int p_what) { float total_max = max_distance; if (area && area->is_using_reverb_bus() && area->get_reverb_uniformity() > 0) { - total_max = MAX(total_max, cam_area_pos.length()); + total_max = MAX(total_max, listener_area_pos.length()); } if (total_max > max_distance) { - continue; //can't hear this sound in this camera + continue; //can't hear this sound in this listener } } @@ -361,8 +377,8 @@ void AudioStreamPlayer3D::_notification(int p_what) { float db_att = (1.0 - MIN(1.0, multiplier)) * attenuation_filter_db; if (emission_angle_enabled) { - Vector3 camtopos = global_pos - camera->get_global_transform().origin; - float c = camtopos.normalized().dot(get_global_transform().basis.get_axis(2).normalized()); //it's z negative + Vector3 listenertopos = global_pos - listener_node->get_global_transform().origin; + float c = listenertopos.normalized().dot(get_global_transform().basis.get_axis(2).normalized()); //it's z negative float angle = Math::rad2deg(Math::acos(c)); if (angle > emission_angle) db_att -= -emission_angle_filter_attenuation_db; @@ -382,8 +398,8 @@ void AudioStreamPlayer3D::_notification(int p_what) { output.vol[0].l = 1.0 - c; output.vol[0].r = c; } else { - Vector3 camtopos = global_pos - camera->get_global_transform().origin; - float c = camtopos.normalized().dot(get_global_transform().basis.get_axis(2).normalized()); //it's z negative + Vector3 listenertopos = global_pos - listener_node->get_global_transform().origin; + float c = listenertopos.normalized().dot(get_global_transform().basis.get_axis(2).normalized()); //it's z negative float angle = Math::rad2deg(Math::acos(c)); float av = angle * (flat_pos.x < 0 ? -1 : 1) / 180.0; @@ -406,20 +422,20 @@ void AudioStreamPlayer3D::_notification(int p_what) { if (cc >= 3) { // Side pair - float sl = Math::abs(1.0 - Math::abs(-0.4 - av)); - float sr = Math::abs(1.0 - Math::abs(0.4 - av)); + float sleft = Math::abs(1.0 - Math::abs(-0.4 - av)); + float sright = Math::abs(1.0 - Math::abs(0.4 - av)); - output.vol[2].l = sl; - output.vol[2].r = sr; + output.vol[2].l = sleft; + output.vol[2].r = sright; } if (cc >= 4) { // Rear pair - float rl = Math::abs(1.0 - Math::abs(-0.2 - av)); - float rr = Math::abs(1.0 - Math::abs(0.2 - av)); + float rleft = Math::abs(1.0 - Math::abs(-0.2 - av)); + float rright = Math::abs(1.0 - Math::abs(0.2 - av)); - output.vol[3].l = rl; - output.vol[3].r = rr; + output.vol[3].l = rleft; + output.vol[3].r = rright; } } @@ -449,7 +465,7 @@ void AudioStreamPlayer3D::_notification(int p_what) { if (uniformity > 0.0) { - float distance = cam_area_pos.length(); + float distance = listener_area_pos.length(); float attenuation = Math::db2linear(_get_attenuation_db(distance)); //float dist_att_db = -20 * Math::log(dist + 0.00001); //logarithmic attenuation, like in real life @@ -459,7 +475,7 @@ void AudioStreamPlayer3D::_notification(int p_what) { if (attenuation < 1.0) { //pan the uniform sound - Vector3 rev_pos = cam_area_pos; + Vector3 rev_pos = listener_area_pos; rev_pos.y = 0; rev_pos.normalize(); @@ -518,9 +534,13 @@ void AudioStreamPlayer3D::_notification(int p_what) { if (doppler_tracking != DOPPLER_TRACKING_DISABLED) { - Vector3 camera_velocity = camera->get_doppler_tracked_velocity(); + Vector3 listener_velocity; + + if (listener_is_camera) { + listener_velocity = camera->get_doppler_tracked_velocity(); + } - Vector3 local_velocity = camera->get_global_transform().orthonormalized().basis.xform_inv(linear_velocity - camera_velocity); + Vector3 local_velocity = listener_node->get_global_transform().orthonormalized().basis.xform_inv(linear_velocity - listener_velocity); if (local_velocity == Vector3()) { output.pitch_scale = 1.0; @@ -642,6 +662,7 @@ float AudioStreamPlayer3D::get_pitch_scale() const { void AudioStreamPlayer3D::play(float p_from_pos) { if (stream_playback.is_valid()) { + stream_stop = false; active = true; setplay = p_from_pos; output_ready = false; @@ -659,9 +680,8 @@ void AudioStreamPlayer3D::seek(float p_seconds) { void AudioStreamPlayer3D::stop() { if (stream_playback.is_valid()) { - active = false; - set_physics_process_internal(false); - setplay = -1; + stream_stop = true; + stream_fade_out = true; } } @@ -855,8 +875,8 @@ void AudioStreamPlayer3D::set_stream_paused(bool p_pause) { if (p_pause != stream_paused) { stream_paused = p_pause; - stream_paused_fade_in = stream_paused ? false : true; - stream_paused_fade_out = stream_paused ? true : false; + stream_fade_in = stream_paused ? false : true; + stream_fade_out = stream_paused ? true : false; } } @@ -994,8 +1014,9 @@ AudioStreamPlayer3D::AudioStreamPlayer3D() { out_of_range_mode = OUT_OF_RANGE_MIX; doppler_tracking = DOPPLER_TRACKING_DISABLED; stream_paused = false; - stream_paused_fade_in = false; - stream_paused_fade_out = false; + stream_fade_in = false; + stream_fade_out = false; + stream_stop = false; velocity_tracker.instance(); AudioServer::get_singleton()->connect("bus_layout_changed", this, "_bus_layout_changed"); diff --git a/scene/3d/audio_stream_player_3d.h b/scene/3d/audio_stream_player_3d.h index 881652da64..e467c170fb 100644 --- a/scene/3d/audio_stream_player_3d.h +++ b/scene/3d/audio_stream_player_3d.h @@ -109,8 +109,9 @@ private: float pitch_scale; bool autoplay; bool stream_paused; - bool stream_paused_fade_in; - bool stream_paused_fade_out; + bool stream_fade_in; + bool stream_fade_out; + bool stream_stop; StringName bus; void _mix_audio(); diff --git a/scene/3d/cpu_particles.cpp b/scene/3d/cpu_particles.cpp index 29610cb0bf..11dfbdb1f9 100644 --- a/scene/3d/cpu_particles.cpp +++ b/scene/3d/cpu_particles.cpp @@ -1238,7 +1238,7 @@ void CPUParticles::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emitting"), "set_emitting", "is_emitting"); ADD_PROPERTY(PropertyInfo(Variant::INT, "amount", PROPERTY_HINT_EXP_RANGE, "1,1000000,1"), "set_amount", "get_amount"); ADD_GROUP("Time", ""); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "lifetime", PROPERTY_HINT_EXP_RANGE, "0.01,600.0,0.01"), "set_lifetime", "get_lifetime"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "lifetime", PROPERTY_HINT_EXP_RANGE, "0.01,600.0,0.01,or_greater"), "set_lifetime", "get_lifetime"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "one_shot"), "set_one_shot", "get_one_shot"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "preprocess", PROPERTY_HINT_EXP_RANGE, "0.00,600.0,0.01"), "set_pre_process_time", "get_pre_process_time"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "speed_scale", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_speed_scale", "get_speed_scale"); diff --git a/scene/3d/navigation_mesh.cpp b/scene/3d/navigation_mesh.cpp index 75301af657..93731c4023 100644 --- a/scene/3d/navigation_mesh.cpp +++ b/scene/3d/navigation_mesh.cpp @@ -292,11 +292,11 @@ Ref<Mesh> NavigationMesh::get_debug_mesh() { if (ek.from < ek.to) SWAP(ek.from, ek.to); - Map<_EdgeKey, bool>::Element *E = edge_map.find(ek); + Map<_EdgeKey, bool>::Element *F = edge_map.find(ek); - if (E) { + if (F) { - E->get() = false; + F->get() = false; } else { diff --git a/scene/3d/particles.cpp b/scene/3d/particles.cpp index 2add50dd5d..57ab01f7be 100644 --- a/scene/3d/particles.cpp +++ b/scene/3d/particles.cpp @@ -29,6 +29,8 @@ /*************************************************************************/ #include "particles.h" + +#include "core/os/os.h" #include "scene/resources/particles_material.h" #include "servers/visual_server.h" @@ -224,6 +226,10 @@ bool Particles::get_fractional_delta() const { String Particles::get_configuration_warning() const { + if (OS::get_singleton()->get_current_video_driver() == OS::VIDEO_DRIVER_GLES2) { + return TTR("GPU-based particles are not supported by the GLES2 video driver.\nUse the CPUParticles node instead. You can use the \"Convert to CPUParticles\" option for this purpose."); + } + String warnings; bool meshes_found = false; @@ -348,7 +354,7 @@ void Particles::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emitting"), "set_emitting", "is_emitting"); ADD_PROPERTY(PropertyInfo(Variant::INT, "amount", PROPERTY_HINT_EXP_RANGE, "1,1000000,1"), "set_amount", "get_amount"); ADD_GROUP("Time", ""); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "lifetime", PROPERTY_HINT_EXP_RANGE, "0.01,600.0,0.01"), "set_lifetime", "get_lifetime"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "lifetime", PROPERTY_HINT_EXP_RANGE, "0.01,600.0,0.01,or_greater"), "set_lifetime", "get_lifetime"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "one_shot"), "set_one_shot", "get_one_shot"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "preprocess", PROPERTY_HINT_EXP_RANGE, "0.00,600.0,0.01"), "set_pre_process_time", "get_pre_process_time"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "speed_scale", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_speed_scale", "get_speed_scale"); diff --git a/scene/3d/path.cpp b/scene/3d/path.cpp index 9fae5a9a54..9005b6b566 100644 --- a/scene/3d/path.cpp +++ b/scene/3d/path.cpp @@ -122,11 +122,10 @@ void PathFollow::_update_transform() { Vector3 pos = c->interpolate_baked(o, cubic); Transform t = get_transform(); // Vector3 pos_offset = Vector3(h_offset, v_offset, 0); not used in all cases - // will be replaced by "Vector3(h_offset, v_offset, 0)" where it was formely used + // will be replaced by "Vector3(h_offset, v_offset, 0)" where it was formerly used if (rotation_mode == ROTATION_ORIENTED) { - Vector3 pos = c->interpolate_baked(o, cubic); Vector3 forward = c->interpolate_baked(o_next, cubic) - pos; if (forward.length_squared() < CMP_EPSILON2) diff --git a/scene/3d/physics_body.cpp b/scene/3d/physics_body.cpp index 50abbd483a..f85b51af08 100644 --- a/scene/3d/physics_body.cpp +++ b/scene/3d/physics_body.cpp @@ -1222,7 +1222,7 @@ Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Ve floor_velocity = collision.collider_vel; if (p_stop_on_slope) { - if (Vector3() == lv_n + p_floor_direction) { + if ((lv_n + p_floor_direction).length() < 0.01) { Transform gt = get_global_transform(); gt.origin -= collision.travel; set_global_transform(gt); @@ -1243,6 +1243,7 @@ Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Ve motion = motion.slide(p_floor_direction); lv = lv.slide(p_floor_direction); } else { + Vector3 n = collision.normal; motion = motion.slide(n); lv = lv.slide(n); @@ -1280,13 +1281,21 @@ Vector3 KinematicBody::move_and_slide_with_snap(const Vector3 &p_linear_velocity Transform gt = get_global_transform(); if (move_and_collide(p_snap, p_infinite_inertia, col, true)) { - gt.origin += col.travel; - if (p_floor_direction != Vector3() && Math::acos(p_floor_direction.normalized().dot(col.normal)) < p_floor_max_angle) { - on_floor = true; - on_floor_body = col.collider_rid; - floor_velocity = col.collider_vel; + + bool apply = true; + if (p_floor_direction != Vector3()) { + if (Math::acos(p_floor_direction.normalized().dot(col.normal)) < p_floor_max_angle) { + on_floor = true; + on_floor_body = col.collider_rid; + floor_velocity = col.collider_vel; + } else { + apply = false; //snapped with floor direction, but did not snap to a floor, do not snap. + } + } + if (apply) { + gt.origin += col.travel; + set_global_transform(gt); } - set_global_transform(gt); } return ret; diff --git a/scene/3d/reflection_probe.h b/scene/3d/reflection_probe.h index 2921a3a881..48d65b79f7 100644 --- a/scene/3d/reflection_probe.h +++ b/scene/3d/reflection_probe.h @@ -32,7 +32,7 @@ #define REFLECTIONPROBE_H #include "scene/3d/visual_instance.h" -#include "scene/resources/sky_box.h" +#include "scene/resources/sky.h" #include "scene/resources/texture.h" #include "servers/visual_server.h" diff --git a/scene/3d/skeleton.cpp b/scene/3d/skeleton.cpp index 8caf4e8e39..ceea50f74a 100644 --- a/scene/3d/skeleton.cpp +++ b/scene/3d/skeleton.cpp @@ -70,9 +70,9 @@ bool Skeleton::_set(const StringName &p_path, const Variant &p_value) { for (int i = 0; i < children.size(); i++) { - NodePath path = children[i]; - ERR_CONTINUE(path.operator String() == ""); - Node *node = get_node(path); + NodePath npath = children[i]; + ERR_CONTINUE(npath.operator String() == ""); + Node *node = get_node(npath); ERR_CONTINUE(!node); bind_child_node_to_bone(which, node); } @@ -115,8 +115,8 @@ bool Skeleton::_get(const StringName &p_path, Variant &r_ret) const { ERR_CONTINUE(!obj); Node *node = Object::cast_to<Node>(obj); ERR_CONTINUE(!node); - NodePath path = get_path_to(node); - children.push_back(path); + NodePath npath = get_path_to(node); + children.push_back(npath); } r_ret = children; @@ -232,7 +232,7 @@ void Skeleton::_notification(int p_what) { Bone *bonesptr = bones.ptrw(); int len = bones.size(); - vs->skeleton_allocate(skeleton, len); // if same size, nothin really happens + vs->skeleton_allocate(skeleton, len); // if same size, nothing really happens _update_process_order(); diff --git a/scene/3d/voxel_light_baker.cpp b/scene/3d/voxel_light_baker.cpp index 30e38c8ee2..42c2318701 100644 --- a/scene/3d/voxel_light_baker.cpp +++ b/scene/3d/voxel_light_baker.cpp @@ -1730,7 +1730,7 @@ Vector3 VoxelLightBaker::_compute_ray_trace_at_pos(const Vector3 &p_pos, const V //int level_limit = max_level; cell = 0; //start from root - for (int i = 0; i < max_level; i++) { + for (int j = 0; j < max_level; j++) { const Cell *bc = &cells[cell]; @@ -1759,14 +1759,14 @@ Vector3 VoxelLightBaker::_compute_ray_trace_at_pos(const Vector3 &p_pos, const V } if (unlikely(cell != CHILD_EMPTY)) { - for (int i = 0; i < 6; i++) { + for (int j = 0; j < 6; j++) { //anisotropic read light - float amount = direction.dot(aniso_normal[i]); + float amount = direction.dot(aniso_normal[j]); if (amount <= 0) continue; - accum.x += light[cell].accum[i][0] * amount; - accum.y += light[cell].accum[i][1] * amount; - accum.z += light[cell].accum[i][2] * amount; + accum.x += light[cell].accum[j][0] * amount; + accum.y += light[cell].accum[j][1] * amount; + accum.z += light[cell].accum[j][2] * amount; } accum.x += cells[cell].emission[0]; accum.y += cells[cell].emission[1]; @@ -1833,16 +1833,16 @@ Error VoxelLightBaker::make_lightmap(const Transform &p_xform, Ref<Mesh> &p_mesh } int faces = ic ? ic / 3 : vc / 3; - for (int i = 0; i < faces; i++) { + for (int j = 0; j < faces; j++) { Vector3 vertex[3]; Vector3 normal[3]; Vector2 uv[3]; - for (int j = 0; j < 3; j++) { - int idx = ic ? ir[i * 3 + j] : i * 3 + j; - vertex[j] = xform.xform(vr[idx]); - normal[j] = xform.basis.xform(nr[idx]).normalized(); - uv[j] = u2r[idx]; + for (int k = 0; k < 3; k++) { + int idx = ic ? ir[j * 3 + k] : j * 3 + k; + vertex[k] = xform.xform(vr[idx]); + normal[k] = xform.basis.xform(nr[idx]).normalized(); + uv[k] = u2r[idx]; } _plot_triangle(uv, vertex, normal, lightmap.ptrw(), width, height); @@ -2208,7 +2208,7 @@ PoolVector<int> VoxelLightBaker::create_gi_probe_data() { } { - uint16_t alpha = CLAMP(uint32_t(bake_cells[i].alpha * 65535.0), 0, 65535); + uint16_t alpha = MAX(uint32_t(bake_cells[i].alpha * 65535.0), 65535); uint16_t level = bake_cells[i].level; w32[ofs++] = (uint32_t(level) << 16) | uint32_t(alpha); diff --git a/scene/3d/scenario_fx.cpp b/scene/3d/world_environment.cpp index ad9b61e1ff..3cd43cbf5b 100644 --- a/scene/3d/scenario_fx.cpp +++ b/scene/3d/world_environment.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* scenario_fx.cpp */ +/* world_environment.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,7 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "scenario_fx.h" +#include "world_environment.h" #include "scene/main/viewport.h" void WorldEnvironment::_notification(int p_what) { diff --git a/scene/3d/scenario_fx.h b/scene/3d/world_environment.h index 6317dae75d..bf36a0a532 100644 --- a/scene/3d/scenario_fx.h +++ b/scene/3d/world_environment.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* scenario_fx.h */ +/* world_environment.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ diff --git a/scene/animation/animation_blend_space_2d.cpp b/scene/animation/animation_blend_space_2d.cpp index 1fe14e633b..95d4644004 100644 --- a/scene/animation/animation_blend_space_2d.cpp +++ b/scene/animation/animation_blend_space_2d.cpp @@ -461,9 +461,9 @@ float AnimationNodeBlendSpace2D::process(float p_time, bool p_seek) { points[j], points[(j + 1) % 3] }; - Vector2 closest = Geometry::get_closest_point_to_segment_2d(blend_pos, s); - if (first || closest.distance_to(blend_pos) < best_point.distance_to(blend_pos)) { - best_point = closest; + Vector2 closest2 = Geometry::get_closest_point_to_segment_2d(blend_pos, s); + if (first || closest2.distance_to(blend_pos) < best_point.distance_to(blend_pos)) { + best_point = closest2; blend_triangle = i; first = false; float d = s[0].distance_to(s[1]); @@ -472,7 +472,7 @@ float AnimationNodeBlendSpace2D::process(float p_time, bool p_seek) { blend_weights[(j + 1) % 3] = 0.0; blend_weights[(j + 2) % 3] = 0.0; } else { - float c = s[0].distance_to(closest) / d; + float c = s[0].distance_to(closest2) / d; blend_weights[j] = 1.0 - c; blend_weights[(j + 1) % 3] = c; diff --git a/scene/animation/animation_cache.cpp b/scene/animation/animation_cache.cpp index 6c67af5777..feefe3ddd4 100644 --- a/scene/animation/animation_cache.cpp +++ b/scene/animation/animation_cache.cpp @@ -133,19 +133,19 @@ void AnimationCache::_update_cache() { } else { if (np.get_subname_count() > 0) { - RES res; + RES res2; Vector<StringName> leftover_subpath; // We don't want to cache the last resource unless it is a method call bool is_method = animation->track_get_type(i) == Animation::TYPE_METHOD; - root->get_node_and_resource(np, res, leftover_subpath, is_method); + root->get_node_and_resource(np, res2, leftover_subpath, is_method); - if (res.is_valid()) { - path.resource = res; + if (res2.is_valid()) { + path.resource = res2; } else { path.node = node; } - path.object = res.is_valid() ? res.ptr() : (Object *)node; + path.object = res2.is_valid() ? res2.ptr() : (Object *)node; path.subpath = leftover_subpath; } else { diff --git a/scene/animation/animation_node_state_machine.cpp b/scene/animation/animation_node_state_machine.cpp index 08cc655cdd..5df3da93e1 100644 --- a/scene/animation/animation_node_state_machine.cpp +++ b/scene/animation/animation_node_state_machine.cpp @@ -421,7 +421,8 @@ float AnimationNodeStateMachinePlayback::process(AnimationNodeStateMachine *sm, if (sm->transitions[i].from == current && auto_advance) { - if (sm->transitions[i].transition->get_priority() < priority_best) { + if (sm->transitions[i].transition->get_priority() <= priority_best) { + priority_best = sm->transitions[i].transition->get_priority(); auto_advance_to = i; } } diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp index 4c249b117e..43ec8cebb0 100644 --- a/scene/animation/animation_player.cpp +++ b/scene/animation/animation_player.cpp @@ -991,25 +991,12 @@ void AnimationPlayer::remove_animation(const StringName &p_name) { void AnimationPlayer::_ref_anim(const Ref<Animation> &p_anim) { - if (used_anims.has(p_anim)) - used_anims[p_anim]++; - else { - used_anims[p_anim] = 1; - Ref<Animation>(p_anim)->connect("changed", this, "_animation_changed"); - } + Ref<Animation>(p_anim)->connect(SceneStringNames::get_singleton()->tracks_changed, this, "_animation_changed", varray(), CONNECT_REFERENCE_COUNTED); } void AnimationPlayer::_unref_anim(const Ref<Animation> &p_anim) { - ERR_FAIL_COND(!used_anims.has(p_anim)); - - int &n = used_anims[p_anim]; - n--; - if (n == 0) { - - Ref<Animation>(p_anim)->disconnect("changed", this, "_animation_changed"); - used_anims.erase(p_anim); - } + Ref<Animation>(p_anim)->disconnect(SceneStringNames::get_singleton()->tracks_changed, this, "_animation_changed"); } void AnimationPlayer::rename_animation(const StringName &p_name, const StringName &p_new_name) { @@ -1205,9 +1192,21 @@ void AnimationPlayer::play(const StringName &p_name, float p_custom_blend, float _stop_playing_caches(); c.current.from = &animation_set[name]; - c.current.pos = p_from_end ? c.current.from->animation->get_length() : 0; + + if (c.assigned != name) { // reset + c.current.pos = p_from_end ? c.current.from->animation->get_length() : 0; + } else { + if (p_from_end && c.current.pos == 0) { + // Animation reset BUT played backwards, set position to the end + c.current.pos = c.current.from->animation->get_length(); + } else if (!p_from_end && c.current.pos == c.current.from->animation->get_length()) { + // Animation resumed but already ended, set position to the beggining + c.current.pos = 0; + } + } + c.current.speed_scale = p_custom_scale; - c.assigned = p_name; + c.assigned = name; c.seeked = false; c.started = true; @@ -1286,6 +1285,7 @@ void AnimationPlayer::stop(bool p_reset) { if (p_reset) { c.current.from = NULL; c.current.speed_scale = 1; + c.current.pos = 0; } _set_process(false); queued.clear(); diff --git a/scene/animation/animation_player.h b/scene/animation/animation_player.h index 175072edcf..fea4819821 100644 --- a/scene/animation/animation_player.h +++ b/scene/animation/animation_player.h @@ -114,10 +114,12 @@ private: Variant value_accum; uint64_t accum_pass; Variant capture; - PropertyAnim() { - accum_pass = 0; - object = NULL; - } + + PropertyAnim() : + owner(NULL), + special(SP_NONE), + object(NULL), + accum_pass(0) {} }; Map<StringName, PropertyAnim> property_anim; @@ -129,25 +131,28 @@ private: float bezier_accum; Object *object; uint64_t accum_pass; - BezierAnim() { - accum_pass = 0; - bezier_accum = 0; - object = NULL; - } + + BezierAnim() : + owner(NULL), + bezier_accum(0.0), + object(NULL), + accum_pass(0) {} }; Map<StringName, BezierAnim> bezier_anim; - TrackNodeCache() { - skeleton = NULL; - spatial = NULL; - node = NULL; - accum_pass = 0; - bone_idx = -1; - node_2d = NULL; - audio_playing = false; - animation_playing = false; - } + TrackNodeCache() : + id(0), + node(NULL), + spatial(NULL), + node_2d(NULL), + skeleton(NULL), + bone_idx(-1), + accum_pass(0), + audio_playing(false), + audio_start(0.0), + audio_len(0.0), + animation_playing(false) {} }; struct TrackNodeCacheKey { @@ -176,8 +181,6 @@ private: int cache_update_bezier_size; Set<TrackNodeCache *> playing_caches; - Map<Ref<Animation>, int> used_anims; - uint64_t accum_pass; float speed_scale; float default_blend_time; diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp index c32001dbcd..0b6fa26bfc 100644 --- a/scene/animation/animation_tree.cpp +++ b/scene/animation/animation_tree.cpp @@ -1009,10 +1009,10 @@ void AnimationTree::_process_graph(float p_delta) { a->method_track_get_key_indices(i, time, delta, &indices); - for (List<int>::Element *E = indices.front(); E; E = E->next()) { + for (List<int>::Element *F = indices.front(); F; F = F->next()) { - StringName method = a->method_track_get_name(i, E->get()); - Vector<Variant> params = a->method_track_get_params(i, E->get()); + StringName method = a->method_track_get_name(i, F->get()); + Vector<Variant> params = a->method_track_get_params(i, F->get()); int s = params.size(); @@ -1151,9 +1151,9 @@ void AnimationTree::_process_graph(float p_delta) { TrackCacheAnimation *t = static_cast<TrackCacheAnimation *>(track); - AnimationPlayer *player = Object::cast_to<AnimationPlayer>(t->object); + AnimationPlayer *player2 = Object::cast_to<AnimationPlayer>(t->object); - if (!player) + if (!player2) continue; if (delta == 0 || seeked) { @@ -1165,10 +1165,10 @@ void AnimationTree::_process_graph(float p_delta) { float pos = a->track_get_key_time(i, idx); StringName anim_name = a->animation_track_get_key_animation(i, idx); - if (String(anim_name) == "[stop]" || !player->has_animation(anim_name)) + if (String(anim_name) == "[stop]" || !player2->has_animation(anim_name)) continue; - Ref<Animation> anim = player->get_animation(anim_name); + Ref<Animation> anim = player2->get_animation(anim_name); float at_anim_pos; @@ -1178,14 +1178,14 @@ void AnimationTree::_process_graph(float p_delta) { at_anim_pos = MAX(anim->get_length(), time - pos); //seek to end } - if (player->is_playing() || seeked) { - player->play(anim_name); - player->seek(at_anim_pos); + if (player2->is_playing() || seeked) { + player2->play(anim_name); + player2->seek(at_anim_pos); t->playing = true; playing_caches.insert(t); } else { - player->set_assigned_animation(anim_name); - player->seek(at_anim_pos, true); + player2->set_assigned_animation(anim_name); + player2->seek(at_anim_pos, true); } } else { //find stuff to play @@ -1195,15 +1195,15 @@ void AnimationTree::_process_graph(float p_delta) { int idx = to_play.back()->get(); StringName anim_name = a->animation_track_get_key_animation(i, idx); - if (String(anim_name) == "[stop]" || !player->has_animation(anim_name)) { + if (String(anim_name) == "[stop]" || !player2->has_animation(anim_name)) { if (playing_caches.has(t)) { playing_caches.erase(t); - player->stop(); + player2->stop(); t->playing = false; } } else { - player->play(anim_name); + player2->play(anim_name); t->playing = true; playing_caches.insert(t); } diff --git a/scene/animation/animation_tree_player.cpp b/scene/animation/animation_tree_player.cpp index e3a21d8b46..3420b48ae3 100644 --- a/scene/animation/animation_tree_player.cpp +++ b/scene/animation/animation_tree_player.cpp @@ -136,9 +136,9 @@ bool AnimationTreePlayer::_set(const StringName &p_name, const Variant &p_value) else animation_node_set_animation(id, node.get_valid("animation")); Array filters = node.get_valid("filter"); - for (int i = 0; i < filters.size(); i++) { + for (int j = 0; j < filters.size(); j++) { - animation_node_set_filter_path(id, filters[i], true); + animation_node_set_filter_path(id, filters[j], true); } } break; case NODE_ONESHOT: { @@ -150,9 +150,9 @@ bool AnimationTreePlayer::_set(const StringName &p_name, const Variant &p_value) oneshot_node_set_autorestart_delay(id, node.get_valid("autorestart_delay")); oneshot_node_set_autorestart_random_delay(id, node.get_valid("autorestart_random_delay")); Array filters = node.get_valid("filter"); - for (int i = 0; i < filters.size(); i++) { + for (int j = 0; j < filters.size(); j++) { - oneshot_node_set_filter_path(id, filters[i], true); + oneshot_node_set_filter_path(id, filters[j], true); } } break; @@ -162,9 +162,9 @@ bool AnimationTreePlayer::_set(const StringName &p_name, const Variant &p_value) case NODE_BLEND2: { blend2_node_set_amount(id, node.get_valid("blend")); Array filters = node.get_valid("filter"); - for (int i = 0; i < filters.size(); i++) { + for (int j = 0; j < filters.size(); j++) { - blend2_node_set_filter_path(id, filters[i], true); + blend2_node_set_filter_path(id, filters[j], true); } } break; case NODE_BLEND3: { @@ -278,8 +278,8 @@ bool AnimationTreePlayer::_get(const StringName &p_name, Variant &r_ret) const { an->filter.get_key_list(&keys); k.resize(keys.size()); int i = 0; - for (List<NodePath>::Element *E = keys.front(); E; E = E->next()) { - k[i++] = E->get(); + for (List<NodePath>::Element *F = keys.front(); F; F = F->next()) { + k[i++] = F->get(); } node["filter"] = k; } break; @@ -297,8 +297,8 @@ bool AnimationTreePlayer::_get(const StringName &p_name, Variant &r_ret) const { osn->filter.get_key_list(&keys); k.resize(keys.size()); int i = 0; - for (List<NodePath>::Element *E = keys.front(); E; E = E->next()) { - k[i++] = E->get(); + for (List<NodePath>::Element *F = keys.front(); F; F = F->next()) { + k[i++] = F->get(); } node["filter"] = k; @@ -315,8 +315,8 @@ bool AnimationTreePlayer::_get(const StringName &p_name, Variant &r_ret) const { bn->filter.get_key_list(&keys); k.resize(keys.size()); int i = 0; - for (List<NodePath>::Element *E = keys.front(); E; E = E->next()) { - k[i++] = E->get(); + for (List<NodePath>::Element *F = keys.front(); F; F = F->next()) { + k[i++] = F->get(); } node["filter"] = k; @@ -874,10 +874,10 @@ void AnimationTreePlayer::_process_animation(float p_delta) { List<int> indices; a->method_track_get_key_indices(tr.local_track, anim_list->time, anim_list->step, &indices); - for (List<int>::Element *E = indices.front(); E; E = E->next()) { + for (List<int>::Element *F = indices.front(); F; F = F->next()) { - StringName method = a->method_track_get_name(tr.local_track, E->get()); - Vector<Variant> args = a->method_track_get_params(tr.local_track, E->get()); + StringName method = a->method_track_get_name(tr.local_track, F->get()); + Vector<Variant> args = a->method_track_get_params(tr.local_track, F->get()); args.resize(VARIANT_ARG_MAX); tr.track->object->call(method, args[0], args[1], args[2], args[3], args[4]); } diff --git a/scene/animation/animation_tree_player.h b/scene/animation/animation_tree_player.h index 12e514f7d5..9ec6325969 100644 --- a/scene/animation/animation_tree_player.h +++ b/scene/animation/animation_tree_player.h @@ -109,6 +109,14 @@ private: Variant value; bool skip; + + Track() : + id(0), + object(NULL), + spatial(NULL), + skeleton(NULL), + bone_idx(-1), + skip(false) {} }; typedef Map<TrackKey, Track> TrackMap; diff --git a/scene/audio/audio_player.cpp b/scene/audio/audio_stream_player.cpp index 4eae3b04e7..5c95cf4279 100644 --- a/scene/audio/audio_player.cpp +++ b/scene/audio/audio_stream_player.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* audio_player.cpp */ +/* audio_stream_player.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,7 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "audio_player.h" +#include "audio_stream_player.h" #include "core/engine.h" @@ -94,10 +94,14 @@ void AudioStreamPlayer::_mix_audio() { if (!stream_playback.is_valid() || !active) return; - if (stream_paused) { - if (stream_paused_fade) { - _mix_internal(true); - stream_paused_fade = false; + if (stream_fade) { + _mix_internal(true); + stream_fade = false; + + if (stream_stop) { + stream_playback->stop(); + active = false; + set_process_internal(false); } return; } @@ -203,6 +207,7 @@ void AudioStreamPlayer::play(float p_from_pos) { if (stream_playback.is_valid()) { //mix_volume_db = volume_db; do not reset volume ramp here, can cause clicks + stream_stop = false; setseek = p_from_pos; active = true; set_process_internal(true); @@ -219,9 +224,8 @@ void AudioStreamPlayer::seek(float p_seconds) { void AudioStreamPlayer::stop() { if (stream_playback.is_valid()) { - stream_playback->stop(); - active = false; - set_process_internal(false); + stream_stop = true; + stream_fade = true; } } @@ -295,7 +299,7 @@ void AudioStreamPlayer::set_stream_paused(bool p_pause) { if (p_pause != stream_paused) { stream_paused = p_pause; - stream_paused_fade = p_pause ? true : false; + stream_fade = p_pause ? true : false; } } @@ -385,7 +389,8 @@ AudioStreamPlayer::AudioStreamPlayer() { setseek = -1; active = false; stream_paused = false; - stream_paused_fade = false; + stream_fade = false; + stream_stop = false; mix_target = MIX_TARGET_STEREO; AudioServer::get_singleton()->connect("bus_layout_changed", this, "_bus_layout_changed"); diff --git a/scene/audio/audio_player.h b/scene/audio/audio_stream_player.h index 2e9526c335..fba8ce7dd3 100644 --- a/scene/audio/audio_player.h +++ b/scene/audio/audio_stream_player.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* audio_player.h */ +/* audio_stream_player.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef AUDIOPLAYER_H -#define AUDIOPLAYER_H +#ifndef AUDIO_STREAM_PLAYER_H +#define AUDIO_STREAM_PLAYER_H #include "scene/main/node.h" #include "servers/audio/audio_stream.h" @@ -58,7 +58,8 @@ private: float volume_db; bool autoplay; bool stream_paused; - bool stream_paused_fade; + bool stream_fade; + bool stream_stop; StringName bus; MixTarget mix_target; @@ -110,4 +111,5 @@ public: }; VARIANT_ENUM_CAST(AudioStreamPlayer::MixTarget) -#endif // AUDIOPLAYER_H + +#endif // AUDIO_STREAM_PLAYER_H diff --git a/scene/gui/button.cpp b/scene/gui/button.cpp index b77b57ddd4..c734136895 100644 --- a/scene/gui/button.cpp +++ b/scene/gui/button.cpp @@ -140,8 +140,8 @@ void Button::_notification(int p_what) { if (has_focus()) { - Ref<StyleBox> style = get_stylebox("focus"); - style->draw(ci, Rect2(Point2(), size)); + Ref<StyleBox> style2 = get_stylebox("focus"); + style2->draw(ci, Rect2(Point2(), size)); } Ref<Font> font = get_font("font"); diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp index 4b1c7b3db7..7aca6acd00 100644 --- a/scene/gui/color_picker.cpp +++ b/scene/gui/color_picker.cpp @@ -737,7 +737,7 @@ ColorPicker::ColorPicker() : bt_add_preset = memnew(Button); bbc->add_child(bt_add_preset); - bt_add_preset->set_tooltip(TTR("Add current color as a preset")); + bt_add_preset->set_tooltip(TTR("Add current color as a preset.")); bt_add_preset->connect("pressed", this, "_add_preset_pressed"); } diff --git a/scene/gui/gradient_edit.h b/scene/gui/gradient_edit.h index fd340b3f6c..662278a17b 100644 --- a/scene/gui/gradient_edit.h +++ b/scene/gui/gradient_edit.h @@ -33,8 +33,8 @@ #include "scene/gui/color_picker.h" #include "scene/gui/popup.h" -#include "scene/resources/color_ramp.h" #include "scene/resources/default_theme/theme_data.h" +#include "scene/resources/gradient.h" #define POINT_WIDTH (8 * EDSCALE) diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp index 94c65b3e64..f3f2e586a6 100644 --- a/scene/gui/graph_edit.cpp +++ b/scene/gui/graph_edit.cpp @@ -221,8 +221,8 @@ void GraphEdit::_graph_node_raised(Node *p_gn) { } int first_not_comment = 0; for (int i = 0; i < get_child_count(); i++) { - GraphNode *gn = Object::cast_to<GraphNode>(get_child(i)); - if (gn && !gn->is_comment()) { + GraphNode *gn2 = Object::cast_to<GraphNode>(get_child(i)); + if (gn2 && !gn2->is_comment()) { first_not_comment = i; break; } @@ -958,33 +958,33 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) { previus_selected.clear(); for (int i = get_child_count() - 1; i >= 0; i--) { - GraphNode *gn = Object::cast_to<GraphNode>(get_child(i)); - if (!gn || !gn->is_selected()) + GraphNode *gn2 = Object::cast_to<GraphNode>(get_child(i)); + if (!gn2 || !gn2->is_selected()) continue; - previus_selected.push_back(gn); + previus_selected.push_back(gn2); } } else if (b->get_shift()) { box_selection_mode_aditive = false; previus_selected.clear(); for (int i = get_child_count() - 1; i >= 0; i--) { - GraphNode *gn = Object::cast_to<GraphNode>(get_child(i)); - if (!gn || !gn->is_selected()) + GraphNode *gn2 = Object::cast_to<GraphNode>(get_child(i)); + if (!gn2 || !gn2->is_selected()) continue; - previus_selected.push_back(gn); + previus_selected.push_back(gn2); } } else { box_selection_mode_aditive = true; previus_selected.clear(); for (int i = get_child_count() - 1; i >= 0; i--) { - GraphNode *gn = Object::cast_to<GraphNode>(get_child(i)); - if (!gn) + GraphNode *gn2 = Object::cast_to<GraphNode>(get_child(i)); + if (!gn2) continue; - gn->set_selected(false); + gn2->set_selected(false); } } } diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp index efe452305b..026374ded1 100644 --- a/scene/gui/item_list.cpp +++ b/scene/gui/item_list.cpp @@ -1094,7 +1094,7 @@ void ItemList::_notification(int p_what) { if (items[i].disabled) modulate.a *= 0.5; - // If the icon is transposed, we have to swith the size so that it is drawn correctly + // If the icon is transposed, we have to switch the size so that it is drawn correctly if (items[i].icon_transposed) { Size2 size_tmp = draw_rect.size; draw_rect.size.x = size_tmp.y; @@ -1114,13 +1114,13 @@ void ItemList::_notification(int p_what) { int max_len = -1; - Vector2 size = font->get_string_size(items[i].text); + Vector2 size2 = font->get_string_size(items[i].text); if (fixed_column_width) max_len = fixed_column_width; else if (same_column_width) max_len = items[i].rect_cache.size.x; else - max_len = size.x; + max_len = size2.x; Color modulate = items[i].selected ? font_color_selected : (items[i].custom_fg != Color() ? items[i].custom_fg : font_color); if (items[i].disabled) @@ -1170,12 +1170,12 @@ void ItemList::_notification(int p_what) { } else { if (fixed_column_width > 0) - size.x = MIN(size.x, fixed_column_width); + size2.x = MIN(size2.x, fixed_column_width); if (icon_mode == ICON_MODE_TOP) { - text_ofs.x += (items[i].rect_cache.size.width - size.x) / 2; + text_ofs.x += (items[i].rect_cache.size.width - size2.x) / 2; } else { - text_ofs.y += (items[i].rect_cache.size.height - size.y) / 2; + text_ofs.y += (items[i].rect_cache.size.height - size2.y) / 2; } text_ofs.y += font->get_ascent(); diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index 4a2bb3dad1..bf6833e512 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -1154,9 +1154,7 @@ void LineEdit::set_cursor_position(int p_pos) { if (cursor_pos <= window_pos) { /* Adjust window if cursor goes too much to the left */ - if (window_pos > 0) - set_window_pos(window_pos - 1); - + set_window_pos(MAX(0, cursor_pos - 1)); } else if (cursor_pos > window_pos) { /* Adjust window if cursor goes too much to the right */ int window_width = get_size().width - style->get_minimum_size().width; diff --git a/scene/gui/link_button.h b/scene/gui/link_button.h index ffe248ac5e..17c4bca67b 100644 --- a/scene/gui/link_button.h +++ b/scene/gui/link_button.h @@ -32,7 +32,7 @@ #define LINKBUTTON_H #include "scene/gui/base_button.h" -#include "scene/resources/bit_mask.h" +#include "scene/resources/bit_map.h" class LinkButton : public BaseButton { diff --git a/scene/gui/option_button.cpp b/scene/gui/option_button.cpp index 98f427cc07..b9b270ce0c 100644 --- a/scene/gui/option_button.cpp +++ b/scene/gui/option_button.cpp @@ -160,6 +160,12 @@ int OptionButton::get_item_id(int p_idx) const { return popup->get_item_id(p_idx); } + +int OptionButton::get_item_index(int p_id) const { + + return popup->get_item_index(p_id); +} + Variant OptionButton::get_item_metadata(int p_idx) const { return popup->get_item_metadata(p_idx); @@ -306,6 +312,7 @@ void OptionButton::_bind_methods() { ClassDB::bind_method(D_METHOD("get_item_text", "idx"), &OptionButton::get_item_text); ClassDB::bind_method(D_METHOD("get_item_icon", "idx"), &OptionButton::get_item_icon); ClassDB::bind_method(D_METHOD("get_item_id", "idx"), &OptionButton::get_item_id); + ClassDB::bind_method(D_METHOD("get_item_index", "id"), &OptionButton::get_item_index); ClassDB::bind_method(D_METHOD("get_item_metadata", "idx"), &OptionButton::get_item_metadata); ClassDB::bind_method(D_METHOD("is_item_disabled", "idx"), &OptionButton::is_item_disabled); ClassDB::bind_method(D_METHOD("get_item_count"), &OptionButton::get_item_count); diff --git a/scene/gui/option_button.h b/scene/gui/option_button.h index 121b4c002d..63b451377a 100644 --- a/scene/gui/option_button.h +++ b/scene/gui/option_button.h @@ -71,6 +71,7 @@ public: String get_item_text(int p_idx) const; Ref<Texture> get_item_icon(int p_idx) const; int get_item_id(int p_idx) const; + int get_item_index(int p_id) const; Variant get_item_metadata(int p_idx) const; bool is_item_disabled(int p_idx) const; diff --git a/scene/gui/popup.cpp b/scene/gui/popup.cpp index 2d2c54594a..80ec7049fc 100644 --- a/scene/gui/popup.cpp +++ b/scene/gui/popup.cpp @@ -124,49 +124,22 @@ void Popup::popup_centered_minsize(const Size2 &p_minsize) { void Popup::popup_centered(const Size2 &p_size) { - Point2 window_size = get_viewport_rect().size; - - emit_signal("about_to_show"); Rect2 rect; + Size2 window_size = get_viewport_rect().size; rect.size = p_size == Size2() ? get_size() : p_size; - rect.position = ((window_size - rect.size) / 2.0).floor(); - set_position(rect.position); - set_size(rect.size); - - show_modal(exclusive); - _fix_size(); - Control *focusable = find_next_valid_focus(); - if (focusable) - focusable->grab_focus(); - - _post_popup(); - notification(NOTIFICATION_POST_POPUP); - popped_up = true; + popup(rect); } void Popup::popup_centered_ratio(float p_screen_ratio) { - emit_signal("about_to_show"); - Rect2 rect; - Point2 window_size = get_viewport_rect().size; + Size2 window_size = get_viewport_rect().size; rect.size = (window_size * p_screen_ratio).floor(); rect.position = ((window_size - rect.size) / 2.0).floor(); - set_position(rect.position); - set_size(rect.size); - show_modal(exclusive); - _fix_size(); - - Control *focusable = find_next_valid_focus(); - if (focusable) - focusable->grab_focus(); - - _post_popup(); - notification(NOTIFICATION_POST_POPUP); - popped_up = true; + popup(rect); } void Popup::popup(const Rect2 &p_bounds) { diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index ac94ac63ec..28b124d143 100644 --- a/scene/gui/popup_menu.cpp +++ b/scene/gui/popup_menu.cpp @@ -519,9 +519,9 @@ void PopupMenu::_notification(int p_what) { if (items[i].accel || (items[i].shortcut.is_valid() && items[i].shortcut->is_valid())) { //accelerator - String text = _get_accel_text(i); - item_ofs.x = size.width - style->get_margin(MARGIN_RIGHT) - font->get_string_size(text).width; - font->draw(ci, item_ofs + Point2(0, Math::floor((h - font_h) / 2.0)), text, i == mouse_over ? font_color_hover : font_color_accel); + String text2 = _get_accel_text(i); + item_ofs.x = size.width - style->get_margin(MARGIN_RIGHT) - font->get_string_size(text2).width; + font->draw(ci, item_ofs + Point2(0, Math::floor((h - font_h) / 2.0)), text2, i == mouse_over ? font_color_hover : font_color_accel); } items.write[i]._ofs_cache = ofs.y; diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index 2e466fd582..d4b008e277 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -544,7 +544,7 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & Vector2 draw_ofs = Point2(wofs, y); Color font_color_shadow = get_color("font_color_shadow"); bool use_outline = get_constant("shadow_as_outline"); - Point2 shadow_ofs(get_constant("shadow_offset_x"), get_constant("shadow_offset_y")); + Point2 shadow_ofs2(get_constant("shadow_offset_x"), get_constant("shadow_offset_y")); if (p_mode == PROCESS_CACHE) { @@ -568,7 +568,7 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & for (int i = 0; i < frame->lines.size(); i++) { - _process_line(frame, Point2(), ly, available_width, i, PROCESS_CACHE, cfont, Color(), font_color_shadow, use_outline, shadow_ofs); + _process_line(frame, Point2(), ly, available_width, i, PROCESS_CACHE, cfont, Color(), font_color_shadow, use_outline, shadow_ofs2); table->columns.write[column].min_width = MAX(table->columns[column].min_width, frame->lines[i].minimum_width); table->columns.write[column].max_width = MAX(table->columns[column].max_width, frame->lines[i].maximum_width); } @@ -641,7 +641,7 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & for (int i = 0; i < frame->lines.size(); i++) { int ly = 0; - _process_line(frame, Point2(), ly, table->columns[column].width, i, PROCESS_CACHE, cfont, Color(), font_color_shadow, use_outline, shadow_ofs); + _process_line(frame, Point2(), ly, table->columns[column].width, i, PROCESS_CACHE, cfont, Color(), font_color_shadow, use_outline, shadow_ofs2); frame->lines.write[i].height_cache = ly; //actual height frame->lines.write[i].height_accum_cache = ly; //actual height } @@ -674,9 +674,9 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & if (visible) { if (p_mode == PROCESS_DRAW) { - nonblank_line_count += _process_line(frame, p_ofs + offset + draw_ofs + Vector2(0, yofs), ly, table->columns[column].width, i, PROCESS_DRAW, cfont, ccolor, font_color_shadow, use_outline, shadow_ofs); + nonblank_line_count += _process_line(frame, p_ofs + offset + draw_ofs + Vector2(0, yofs), ly, table->columns[column].width, i, PROCESS_DRAW, cfont, ccolor, font_color_shadow, use_outline, shadow_ofs2); } else if (p_mode == PROCESS_POINTER) { - _process_line(frame, p_ofs + offset + draw_ofs + Vector2(0, yofs), ly, table->columns[column].width, i, PROCESS_POINTER, cfont, ccolor, font_color_shadow, use_outline, shadow_ofs, p_click_pos, r_click_item, r_click_char, r_outside); + _process_line(frame, p_ofs + offset + draw_ofs + Vector2(0, yofs), ly, table->columns[column].width, i, PROCESS_POINTER, cfont, ccolor, font_color_shadow, use_outline, shadow_ofs2, p_click_pos, r_click_item, r_click_char, r_outside); if (r_click_item && *r_click_item) { RETURN; // exit early } diff --git a/scene/gui/split_container.cpp b/scene/gui/split_container.cpp index d6a93238b2..e947216a3a 100644 --- a/scene/gui/split_container.cpp +++ b/scene/gui/split_container.cpp @@ -164,11 +164,6 @@ void SplitContainer::_notification(int p_what) { _resort(); } break; - case NOTIFICATION_MOUSE_ENTER: { - - mouse_inside = true; - update(); - } break; case NOTIFICATION_MOUSE_EXIT: { mouse_inside = false; @@ -182,16 +177,17 @@ void SplitContainer::_notification(int p_what) { if (collapsed || (!mouse_inside && get_constant("autohide"))) return; + if (dragger_visibility != DRAGGER_VISIBLE) + return; + int sep = dragger_visibility != DRAGGER_HIDDEN_COLLAPSED ? get_constant("separation") : 0; Ref<Texture> tex = get_icon("grabber"); Size2 size = get_size(); - if (dragger_visibility == DRAGGER_VISIBLE) { - if (vertical) - draw_texture(tex, Point2i((size.x - tex->get_width()) / 2, middle_sep + (sep - tex->get_height()) / 2)); - else - draw_texture(tex, Point2i(middle_sep + (sep - tex->get_width()) / 2, (size.y - tex->get_height()) / 2)); - } + if (vertical) + draw_texture(tex, Point2i((size.x - tex->get_width()) / 2, middle_sep + (sep - tex->get_height()) / 2)); + else + draw_texture(tex, Point2i(middle_sep + (sep - tex->get_width()) / 2, (size.y - tex->get_height()) / 2)); } break; case NOTIFICATION_THEME_CHANGED: { @@ -241,7 +237,22 @@ void SplitContainer::_gui_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseMotion> mm = p_event; - if (mm.is_valid() && dragging) { + if (mm.is_valid()) { + + bool mouse_inside_state = false; + if (vertical) + mouse_inside_state = mm->get_position().y > middle_sep && mm->get_position().y < middle_sep + get_constant("separation"); + else + mouse_inside_state = mm->get_position().x > middle_sep && mm->get_position().x < middle_sep + get_constant("separation"); + + if (mouse_inside != mouse_inside_state) { + + mouse_inside = mouse_inside_state; + update(); + } + + if (!dragging) + return; split_offset = drag_ofs + ((vertical ? mm->get_position().y : mm->get_position().x) - drag_from); should_clamp_split_offset = true; diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index 4abde6cc0f..f38bc62a3c 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -861,6 +861,9 @@ void TextEdit::_notification(int p_what) { const String &str = wrap_rows[line_wrap_index]; int indent_px = line_wrap_index != 0 ? get_indent_level(line) * cache.font->get_char_size(' ').width : 0; + if (indent_px >= wrap_at) { + indent_px = 0; + } if (line_wrap_index > 0) last_wrap_column += wrap_rows[line_wrap_index - 1].length(); @@ -1381,8 +1384,8 @@ void TextEdit::_notification(int p_what) { } } - Size2 size = Size2(max_w, sc * font->get_height() + spacing); - Size2 minsize = size + sb->get_minimum_size(); + Size2 size2 = Size2(max_w, sc * font->get_height() + spacing); + Size2 minsize = size2 + sb->get_minimum_size(); if (completion_hint_offset == -0xFFFF) { completion_hint_offset = cursor_pos.x - offset; @@ -1714,10 +1717,10 @@ void TextEdit::_get_mouse_pos(const Point2i &p_mouse, int &r_row, int &r_col) co col = get_char_pos_for_line(colx, row, wrap_index); if (is_wrap_enabled() && wrap_index < times_line_wraps(row)) { // move back one if we are at the end of the row - Vector<String> rows = get_wrap_rows_text(row); + Vector<String> rows2 = get_wrap_rows_text(row); int row_end_col = 0; for (int i = 0; i < wrap_index + 1; i++) { - row_end_col += rows[i].length(); + row_end_col += rows2[i].length(); } if (col >= row_end_col) col -= 1; @@ -2202,10 +2205,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { bool had_selection = selection.active; // stuff to do when selection is active.. - if (selection.active) { - - if (readonly) - return; + if (!readonly && selection.active) { bool clear = false; bool unselect = false; @@ -3375,20 +3375,20 @@ void TextEdit::_base_insert_text(int p_line, int p_char, const String &p_text, i String preinsert_text = text[p_line].substr(0, p_char); String postinsert_text = text[p_line].substr(p_char, text[p_line].size()); - for (int i = 0; i < substrings.size(); i++) { + for (int j = 0; j < substrings.size(); j++) { //insert the substrings - if (i == 0) { + if (j == 0) { - text.set(p_line, preinsert_text + substrings[i]); + text.set(p_line, preinsert_text + substrings[j]); } else { - text.insert(p_line + i, substrings[i]); + text.insert(p_line + j, substrings[j]); } - if (i == substrings.size() - 1) { + if (j == substrings.size() - 1) { - text.set(p_line + i, text[p_line + i] + postinsert_text); + text.set(p_line + j, text[p_line + j] + postinsert_text); } } @@ -3791,6 +3791,9 @@ Vector<String> TextEdit::get_wrap_rows_text(int p_line) const { int cur_wrap_index = 0; int tab_offset_px = get_indent_level(p_line) * cache.font->get_char_size(' ').width; + if (tab_offset_px >= wrap_at) { + tab_offset_px = 0; + } while (col < line_text.length()) { CharType c = line_text[col]; @@ -3798,29 +3801,36 @@ Vector<String> TextEdit::get_wrap_rows_text(int p_line) const { int indent_ofs = (cur_wrap_index != 0 ? tab_offset_px : 0); - word_str += c; - word_px += w; - if (c == ' ') { - // end of a word; add this word to the substring + if (indent_ofs + word_px + w > wrap_at) { + // not enough space to add this char; start next line wrap_substring += word_str; - px += word_px; - word_str = ""; - word_px = 0; - } + lines.push_back(wrap_substring); + cur_wrap_index++; + wrap_substring = ""; + px = 0; - if ((indent_ofs + px + word_px) > wrap_at) { - // do not want to add this word - if (indent_ofs + word_px > wrap_at) { - // not enough space; add it anyway + word_str = ""; + word_str += c; + word_px = w; + } else { + word_str += c; + word_px += w; + if (c == ' ') { + // end of a word; add this word to the substring wrap_substring += word_str; + px += word_px; word_str = ""; word_px = 0; } - lines.push_back(wrap_substring); - // reset for next wrap - cur_wrap_index++; - wrap_substring = ""; - px = 0; + + if (indent_ofs + px + word_px > wrap_at) { + // this word will be moved to the next line + lines.push_back(wrap_substring); + // reset for next wrap + cur_wrap_index++; + wrap_substring = ""; + px = 0; + } } col++; } @@ -4033,6 +4043,9 @@ int TextEdit::get_char_pos_for_line(int p_px, int p_line, int p_wrap_index) cons int line_wrap_amount = times_line_wraps(p_line); int wrap_offset_px = get_indent_level(p_line) * cache.font->get_char_size(' ').width; + if (wrap_offset_px >= wrap_at) { + wrap_offset_px = 0; + } if (p_wrap_index > line_wrap_amount) p_wrap_index = line_wrap_amount; if (p_wrap_index > 0) @@ -4074,6 +4087,9 @@ int TextEdit::get_column_x_offset_for_line(int p_char, int p_line) const { int px = get_column_x_offset(n_char, rows[wrap_index]); int wrap_offset_px = get_indent_level(p_line) * cache.font->get_char_size(' ').width; + if (wrap_offset_px >= wrap_at) { + wrap_offset_px = 0; + } if (wrap_index != 0) px += wrap_offset_px; diff --git a/scene/gui/texture_button.cpp b/scene/gui/texture_button.cpp index 95aab95253..19bef9fdf5 100644 --- a/scene/gui/texture_button.cpp +++ b/scene/gui/texture_button.cpp @@ -64,7 +64,9 @@ bool TextureButton::has_point(const Point2 &p_point) const { Rect2 rect = Rect2(); Size2 mask_size = click_mask->get_size(); - if (_tile) { + if (_position_rect.no_area()) { + rect.size = mask_size; + } else if (_tile) { // if the stretch mode is tile we offset the point to keep it inside the mask size rect.size = mask_size; if (_position_rect.has_point(point)) { @@ -206,8 +208,8 @@ void TextureButton::_notification(int p_what) { Size2 scaleSize(size.width / tex_size.width, size.height / tex_size.height); float scale = scaleSize.width > scaleSize.height ? scaleSize.width : scaleSize.height; Size2 scaledTexSize = tex_size * scale; - Point2 ofs = ((scaledTexSize - size) / scale).abs() / 2.0f; - _texture_region = Rect2(ofs, size / scale); + Point2 ofs2 = ((scaledTexSize - size) / scale).abs() / 2.0f; + _texture_region = Rect2(ofs2, size / scale); } break; } } @@ -216,6 +218,8 @@ void TextureButton::_notification(int p_what) { draw_texture_rect(texdraw, _position_rect, _tile); else draw_texture_rect_region(texdraw, _position_rect, _texture_region); + } else { + _position_rect = Rect2(); } if (has_focus() && focused.is_valid()) { diff --git a/scene/gui/texture_button.h b/scene/gui/texture_button.h index 4dc0de5358..d9224de686 100644 --- a/scene/gui/texture_button.h +++ b/scene/gui/texture_button.h @@ -32,7 +32,7 @@ #define TEXTURE_BUTTON_H #include "scene/gui/base_button.h" -#include "scene/resources/bit_mask.h" +#include "scene/resources/bit_map.h" class TextureButton : public BaseButton { GDCLASS(TextureButton, BaseButton); diff --git a/scene/gui/texture_progress.cpp b/scene/gui/texture_progress.cpp index 778d86d546..c534df5cbe 100644 --- a/scene/gui/texture_progress.cpp +++ b/scene/gui/texture_progress.cpp @@ -160,23 +160,27 @@ Point2 TextureProgress::unit_val_to_uv(float val) { if (edge == 0) { if (dir.x > 0) continue; - cp = -dir.x; cq = -(edgeLeft - p.x); + dir.x *= 2.0 * cq; + cp = -dir.x; } else if (edge == 1) { if (dir.x < 0) continue; - cp = dir.x; cq = (edgeRight - p.x); + dir.x *= 2.0 * cq; + cp = dir.x; } else if (edge == 2) { if (dir.y > 0) continue; - cp = -dir.y; cq = -(edgeBottom - p.y); + dir.y *= 2.0 * cq; + cp = -dir.y; } else if (edge == 3) { if (dir.y < 0) continue; - cp = dir.y; cq = (edgeTop - p.y); + dir.y *= 2.0 * cq; + cp = dir.y; } cr = cq / cp; if (cr >= 0 && cr < t1) @@ -247,12 +251,14 @@ void TextureProgress::draw_nine_patch_stretched(const Ref<Texture> &p_texture, F middle_section_size *= MIN(1.0, (MAX(0.0, width_filled - first_section_size) / MAX(1.0, width_total - first_section_size - last_section_size))); last_section_size = MAX(0.0, last_section_size - (width_total - width_filled)); + first_section_size = MIN(first_section_size, width_filled); width_texture = MIN(width_texture, first_section_size + middle_section_size + last_section_size); switch (mode) { case FILL_LEFT_TO_RIGHT: { src_rect.size.x = width_texture; dst_rect.size.x = width_filled; + topleft.x = first_section_size; bottomright.x = last_section_size; } break; case FILL_RIGHT_TO_LEFT: { @@ -261,11 +267,13 @@ void TextureProgress::draw_nine_patch_stretched(const Ref<Texture> &p_texture, F dst_rect.position.x += width_total - width_filled; dst_rect.size.x = width_filled; topleft.x = last_section_size; + bottomright.x = first_section_size; } break; case FILL_TOP_TO_BOTTOM: { src_rect.size.y = width_texture; dst_rect.size.y = width_filled; bottomright.y = last_section_size; + topleft.y = first_section_size; } break; case FILL_BOTTOM_TO_TOP: { src_rect.position.y += src_rect.size.y - width_texture; @@ -273,6 +281,7 @@ void TextureProgress::draw_nine_patch_stretched(const Ref<Texture> &p_texture, F dst_rect.position.y += width_total - width_filled; dst_rect.size.y = width_filled; topleft.y = last_section_size; + bottomright.y = first_section_size; } break; case FILL_BILINEAR_LEFT_AND_RIGHT: { // TODO: Implement diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index 514be00227..236c4dbe63 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -1071,11 +1071,11 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 int font_ascent = font->get_ascent(); int ofs = p_pos.x + ((p_item->disable_folding || hide_folding) ? cache.hseparation : cache.item_margin); - int skip = 0; + int skip2 = 0; for (int i = 0; i < columns.size(); i++) { - if (skip) { - skip--; + if (skip2) { + skip2--; continue; } @@ -1102,7 +1102,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 while (i + plus < columns.size() && !p_item->cells[i + plus].editable && p_item->cells[i + plus].mode == TreeItem::CELL_MODE_STRING && p_item->cells[i + plus].text == "" && p_item->cells[i + plus].icon.is_null()) { w += get_column_width(i + plus); plus++; - skip++; + skip2++; } } @@ -1165,8 +1165,8 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 cache.selected->draw(ci, r); } if (text_editor->is_visible_in_tree()) { - Vector2 ofs(0, (text_editor->get_size().height - r.size.height) / 2); - text_editor->set_position(get_global_position() + r.position - ofs); + Vector2 ofs2(0, (text_editor->get_size().height - r.size.height) / 2); + text_editor->set_position(get_global_position() + r.position - ofs2); } } @@ -1601,7 +1601,7 @@ void Tree::_range_click_timeout() { mb.instance(); ; - propagate_mouse_activated = false; //done from outside, so signal handler cant clear the tree in the middle of emit(which is a common case) + propagate_mouse_activated = false; // done from outside, so signal handler can't clear the tree in the middle of emit (which is a common case) blocked++; propagate_mouse_event(pos + cache.offset, 0, 0, false, root, BUTTON_LEFT, mb); blocked--; @@ -2698,8 +2698,8 @@ bool Tree::edit_selected() { popup_menu->clear(); for (int i = 0; i < c.text.get_slice_count(","); i++) { - String s = c.text.get_slicec(',', i); - popup_menu->add_item(s.get_slicec(':', 0), s.get_slicec(':', 1).empty() ? i : s.get_slicec(':', 1).to_int()); + String s2 = c.text.get_slicec(',', i); + popup_menu->add_item(s2.get_slicec(':', 0), s2.get_slicec(':', 1).empty() ? i : s2.get_slicec(':', 1).to_int()); } popup_menu->set_size(Size2(rect.size.width, 0)); @@ -2951,14 +2951,14 @@ void Tree::_notification(int p_what) { if (show_column_titles) { //title buttons - int ofs = cache.bg->get_margin(MARGIN_LEFT); + int ofs2 = cache.bg->get_margin(MARGIN_LEFT); for (int i = 0; i < columns.size(); i++) { Ref<StyleBox> sb = (cache.click_type == Cache::CLICK_TITLE && cache.click_index == i) ? cache.title_button_pressed : ((cache.hover_type == Cache::CLICK_TITLE && cache.hover_index == i) ? cache.title_button_hover : cache.title_button); Ref<Font> f = cache.tb_font; - Rect2 tbrect = Rect2(ofs - cache.offset.x, bg->get_margin(MARGIN_TOP), get_column_width(i), tbh); + Rect2 tbrect = Rect2(ofs2 - cache.offset.x, bg->get_margin(MARGIN_TOP), get_column_width(i), tbh); sb->draw(ci, tbrect); - ofs += tbrect.size.width; + ofs2 += tbrect.size.width; //text int clip_w = tbrect.size.width - sb->get_minimum_size().width; f->draw_halign(ci, tbrect.position + Point2i(sb->get_offset().x, (tbrect.size.height - f->get_height()) / 2 + f->get_ascent()), HALIGN_CENTER, clip_w, columns[i].title, cache.title_button_color); diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 6aa3891035..04d7107fa4 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -1311,7 +1311,7 @@ Node *Node::_get_child_by_name(const StringName &p_name) const { return NULL; } -Node *Node::_get_node(const NodePath &p_path) const { +Node *Node::get_node_or_null(const NodePath &p_path) const { if (!data.inside_tree && p_path.is_absolute()) { ERR_EXPLAIN("Can't use get_node() with absolute paths from outside the active scene tree."); @@ -1376,7 +1376,7 @@ Node *Node::_get_node(const NodePath &p_path) const { Node *Node::get_node(const NodePath &p_path) const { - Node *node = _get_node(p_path); + Node *node = get_node_or_null(p_path); if (!node) { ERR_EXPLAIN("Node not found: " + p_path); ERR_FAIL_COND_V(!node, NULL); @@ -1386,7 +1386,7 @@ Node *Node::get_node(const NodePath &p_path) const { bool Node::has_node(const NodePath &p_path) const { - return _get_node(p_path) != NULL; + return get_node_or_null(p_path) != NULL; } Node *Node::find_node(const String &p_mask, bool p_recursive, bool p_owned) const { @@ -2709,6 +2709,7 @@ void Node::_bind_methods() { ClassDB::bind_method(D_METHOD("get_child", "idx"), &Node::get_child); ClassDB::bind_method(D_METHOD("has_node", "path"), &Node::has_node); ClassDB::bind_method(D_METHOD("get_node", "path"), &Node::get_node); + ClassDB::bind_method(D_METHOD("get_node_or_null", "path"), &Node::get_node_or_null); ClassDB::bind_method(D_METHOD("get_parent"), &Node::get_parent); ClassDB::bind_method(D_METHOD("find_node", "mask", "recursive", "owned"), &Node::find_node, DEFVAL(true), DEFVAL(true)); ClassDB::bind_method(D_METHOD("find_parent", "mask"), &Node::find_parent); diff --git a/scene/main/node.h b/scene/main/node.h index 1c451ef567..e6189389cb 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -153,7 +153,6 @@ private: void _print_tree_pretty(const String prefix, const bool last); void _print_tree(const Node *p_node); - Node *_get_node(const NodePath &p_path) const; Node *_get_child_by_name(const StringName &p_name) const; void _replace_connections_target(Node *p_new_target); @@ -252,6 +251,7 @@ public: Node *get_child(int p_index) const; bool has_node(const NodePath &p_path) const; Node *get_node(const NodePath &p_path) const; + Node *get_node_or_null(const NodePath &p_path) const; Node *find_node(const String &p_mask, bool p_recursive = true, bool p_owned = true) const; bool has_node_and_resource(const NodePath &p_path) const; Node *get_node_and_resource(const NodePath &p_path, RES &r_res, Vector<StringName> &r_leftover_subpath, bool p_last_is_property = true) const; diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp index f713851090..689f18a09d 100644 --- a/scene/main/scene_tree.cpp +++ b/scene/main/scene_tree.cpp @@ -1154,13 +1154,14 @@ void SceneTree::_update_root_rect() { float viewport_aspect = desired_res.aspect(); float video_mode_aspect = video_mode.aspect(); + if (use_font_oversampling && stretch_aspect == STRETCH_ASPECT_IGNORE) { + WARN_PRINT("Font oversampling only works with the resize modes 'Keep Width', 'Keep Height', and 'Expand'."); + } + if (stretch_aspect == STRETCH_ASPECT_IGNORE || ABS(viewport_aspect - video_mode_aspect) < CMP_EPSILON) { //same aspect or ignore aspect viewport_size = desired_res; screen_size = video_mode; - if (use_font_oversampling) { - WARN_PRINT("Font oversampling only works with the following resize modes 'Keep Width', 'Keep Height', and 'Expand'.") - } } else if (viewport_aspect < video_mode_aspect) { // screen ratio is smaller vertically diff --git a/scene/main/scene_tree.h b/scene/main/scene_tree.h index 3a1ff5cb06..e15a64604d 100644 --- a/scene/main/scene_tree.h +++ b/scene/main/scene_tree.h @@ -43,7 +43,6 @@ @author Juan Linietsky <reduzio@gmail.com> */ -class SceneTree; class PackedScene; class Node; class Viewport; diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 61d6fc7401..090e6bdcb0 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -37,8 +37,8 @@ #include "scene/3d/camera.h" #include "scene/3d/collision_object.h" #include "scene/3d/listener.h" -#include "scene/3d/scenario_fx.h" #include "scene/3d/spatial.h" +#include "scene/3d/world_environment.h" #include "scene/gui/control.h" #include "scene/gui/label.h" #include "scene/gui/menu_button.h" @@ -239,7 +239,7 @@ void Viewport::_collision_object_input_event(CollisionObject *p_object, Camera * ObjectID id = p_object->get_instance_id(); if (p_discard_empty_motion) { - //avoid sending the event unnecesarily if nothing really changed in the context + //avoid sending the event unnecessarily if nothing really changed in the context Ref<InputEventMouseMotion> mm = p_input_event; if (mm.is_valid() && object_transform == physics_last_object_transform && camera_transform == physics_last_camera_transform && physics_last_id == id) { return; //discarded @@ -425,7 +425,7 @@ void Viewport::_notification(int p_what) { bool discard_empty_motion = false; { // if no motion event exists, create a new one. This is necessary because objects or camera may have moved. - // while this extra event is sent, it is checked if both camera and last object and last ID did not move. If nothing changed, the event is discarded to avoid flooding with unnecesary motion events every frame + // while this extra event is sent, it is checked if both camera and last object and last ID did not move. If nothing changed, the event is discarded to avoid flooding with unnecessary motion events every frame bool has_mouse_motion = false; for (List<Ref<InputEvent> >::Element *E = physics_picking_events.front(); E; E = E->next()) { Ref<InputEventMouseMotion> mm = E->get(); @@ -540,12 +540,12 @@ void Viewport::_notification(int p_what) { CollisionObject2D *co = Object::cast_to<CollisionObject2D>(res[i].collider); if (co) { - Map<ObjectID, uint64_t>::Element *E = physics_2d_mouseover.find(res[i].collider_id); - if (!E) { - E = physics_2d_mouseover.insert(res[i].collider_id, frame); + Map<ObjectID, uint64_t>::Element *F = physics_2d_mouseover.find(res[i].collider_id); + if (!F) { + F = physics_2d_mouseover.insert(res[i].collider_id, frame); co->_mouse_enter(); } else { - E->get() = frame; + F->get() = frame; } co->_input_event(this, ev, res[i].shape); @@ -1747,8 +1747,8 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { while (!gui.modal_stack.empty()) { Control *top = gui.modal_stack.back()->get(); - Vector2 pos = top->get_global_transform_with_canvas().affine_inverse().xform(mpos); - if (!top->has_point(pos)) { + Vector2 pos2 = top->get_global_transform_with_canvas().affine_inverse().xform(mpos); + if (!top->has_point(pos2)) { if (top->data.modal_exclusive || top->data.modal_frame == Engine::get_singleton()->get_frames_drawn()) { //cancel event, sorry, modal exclusive EATS UP ALL @@ -2496,6 +2496,9 @@ void Viewport::_gui_remove_control(Control *p_control) { gui.mouse_focus = NULL; gui.mouse_focus_mask = 0; } + if (gui.last_mouse_focus == p_control) { + gui.last_mouse_focus = NULL; + } if (gui.key_focus == p_control) gui.key_focus = NULL; if (gui.mouse_over == p_control) @@ -3199,6 +3202,8 @@ Viewport::Viewport() { gui.drag_attempted = false; gui.canvas_sort_index = 0; gui.roots_order_dirty = false; + gui.mouse_focus = NULL; + gui.last_mouse_focus = NULL; msaa = MSAA_DISABLED; hdr = true; diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index a50a09f095..49c9c4c23c 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -48,7 +48,7 @@ #include "scene/2d/light_occluder_2d.h" #include "scene/2d/line_2d.h" #include "scene/2d/mesh_instance_2d.h" -#include "scene/2d/navigation2d.h" +#include "scene/2d/navigation_2d.h" #include "scene/2d/parallax_background.h" #include "scene/2d/parallax_layer.h" #include "scene/2d/particles_2d.h" @@ -58,10 +58,10 @@ #include "scene/2d/position_2d.h" #include "scene/2d/ray_cast_2d.h" #include "scene/2d/remote_transform_2d.h" -#include "scene/2d/screen_button.h" #include "scene/2d/skeleton_2d.h" #include "scene/2d/sprite.h" #include "scene/2d/tile_map.h" +#include "scene/2d/touch_screen_button.h" #include "scene/2d/visibility_notifier_2d.h" #include "scene/2d/y_sort.h" #include "scene/animation/animation_blend_space_1d.h" @@ -73,7 +73,7 @@ #include "scene/animation/animation_tree_player.h" #include "scene/animation/root_motion_view.h" #include "scene/animation/tween.h" -#include "scene/audio/audio_player.h" +#include "scene/audio/audio_stream_player.h" #include "scene/gui/box_container.h" #include "scene/gui/button.h" #include "scene/gui/center_container.h" @@ -125,12 +125,11 @@ #include "scene/main/timer.h" #include "scene/main/viewport.h" #include "scene/resources/audio_stream_sample.h" -#include "scene/resources/bit_mask.h" +#include "scene/resources/bit_map.h" #include "scene/resources/box_shape.h" #include "scene/resources/capsule_shape.h" #include "scene/resources/capsule_shape_2d.h" #include "scene/resources/circle_shape_2d.h" -#include "scene/resources/color_ramp.h" #include "scene/resources/concave_polygon_shape.h" #include "scene/resources/concave_polygon_shape_2d.h" #include "scene/resources/convex_polygon_shape.h" @@ -139,21 +138,23 @@ #include "scene/resources/default_theme/default_theme.h" #include "scene/resources/dynamic_font.h" #include "scene/resources/dynamic_font_stb.h" +#include "scene/resources/gradient.h" +#include "scene/resources/line_shape_2d.h" #include "scene/resources/material.h" #include "scene/resources/mesh.h" #include "scene/resources/mesh_data_tool.h" #include "scene/resources/mesh_library.h" #include "scene/resources/packed_scene.h" #include "scene/resources/particles_material.h" +#include "scene/resources/physics_material.h" #include "scene/resources/plane_shape.h" #include "scene/resources/polygon_path_finder.h" #include "scene/resources/primitive_meshes.h" #include "scene/resources/ray_shape.h" #include "scene/resources/rectangle_shape_2d.h" -#include "scene/resources/scene_format_text.h" +#include "scene/resources/resource_format_text.h" #include "scene/resources/segment_shape_2d.h" -#include "scene/resources/shape_line_2d.h" -#include "scene/resources/sky_box.h" +#include "scene/resources/sky.h" #include "scene/resources/sphere_shape.h" #include "scene/resources/surface_tool.h" #include "scene/resources/text_file.h" @@ -166,8 +167,8 @@ #include "scene/resources/world_2d.h" #include "scene/scene_string_names.h" -#include "scene/3d/scenario_fx.h" #include "scene/3d/spatial.h" +#include "scene/3d/world_environment.h" #ifndef _3D_DISABLED #include "scene/3d/area.h" @@ -207,7 +208,6 @@ #include "scene/3d/visibility_notifier.h" #include "scene/animation/skeleton_ik.h" #include "scene/resources/environment.h" -#include "scene/resources/physics_material.h" #endif static Ref<ResourceFormatSaverText> resource_saver_text; @@ -602,8 +602,8 @@ void register_scene_types() { ClassDB::register_class<SpatialVelocityTracker>(); - ClassDB::register_class<PhysicsMaterial>(); #endif + ClassDB::register_class<PhysicsMaterial>(); ClassDB::register_class<World>(); ClassDB::register_class<Environment>(); ClassDB::register_class<World2D>(); diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp index 3156e12c50..2af92a788e 100644 --- a/scene/resources/animation.cpp +++ b/scene/resources/animation.cpp @@ -29,6 +29,7 @@ /*************************************************************************/ #include "animation.h" +#include "scene/scene_string_names.h" #include "core/math/geometry.h" @@ -268,19 +269,19 @@ bool Animation::_set(const StringName &p_name, const Variant &p_value) { for (int i = 0; i < valcount; i++) { - Dictionary d = clips[i]; - if (!d.has("start_offset")) + Dictionary d2 = clips[i]; + if (!d2.has("start_offset")) continue; - if (!d.has("end_offset")) + if (!d2.has("end_offset")) continue; - if (!d.has("stream")) + if (!d2.has("stream")) continue; TKey<AudioKey> ak; ak.time = rt[i]; - ak.value.start_offset = d["start_offset"]; - ak.value.end_offset = d["end_offset"]; - ak.value.stream = d["stream"]; + ak.value.start_offset = d2["start_offset"]; + ak.value.end_offset = d2["end_offset"]; + ak.value.stream = d2["stream"]; ad->values.push_back(ak); } @@ -668,6 +669,7 @@ int Animation::add_track(TrackType p_type, int p_at_pos) { } } emit_changed(); + emit_signal(SceneStringNames::get_singleton()->tracks_changed); return p_at_pos; } @@ -719,6 +721,7 @@ void Animation::remove_track(int p_track) { memdelete(t); tracks.remove(p_track); emit_changed(); + emit_signal(SceneStringNames::get_singleton()->tracks_changed); } int Animation::get_track_count() const { @@ -737,6 +740,7 @@ void Animation::track_set_path(int p_track, const NodePath &p_path) { ERR_FAIL_INDEX(p_track, tracks.size()); tracks[p_track]->path = p_path; emit_changed(); + emit_signal(SceneStringNames::get_singleton()->tracks_changed); } NodePath Animation::track_get_path(int p_track) const { @@ -1410,6 +1414,8 @@ void Animation::track_set_key_value(int p_track, int p_key_idx, const Variant &p } break; } + + emit_changed(); } void Animation::track_set_key_transition(int p_track, int p_key_idx, float p_transition) { @@ -1445,6 +1451,8 @@ void Animation::track_set_key_transition(int p_track, int p_key_idx, float p_tra // they don't use transition } break; } + + emit_changed(); } template <class K> @@ -2554,6 +2562,7 @@ void Animation::track_move_up(int p_track) { } emit_changed(); + emit_signal(SceneStringNames::get_singleton()->tracks_changed); } void Animation::track_set_imported(int p_track, bool p_imported) { @@ -2588,6 +2597,7 @@ void Animation::track_move_down(int p_track) { SWAP(tracks.write[p_track], tracks.write[p_track - 1]); } emit_changed(); + emit_signal(SceneStringNames::get_singleton()->tracks_changed); } void Animation::track_swap(int p_track, int p_with_track) { @@ -2598,6 +2608,7 @@ void Animation::track_swap(int p_track, int p_with_track) { return; SWAP(tracks.write[p_track], tracks.write[p_with_track]); emit_changed(); + emit_signal(SceneStringNames::get_singleton()->tracks_changed); } void Animation::set_step(float p_step) { @@ -2716,6 +2727,8 @@ void Animation::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "loop"), "set_loop", "has_loop"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "step", PROPERTY_HINT_RANGE, "0,4096,0.001"), "set_step", "get_step"); + ADD_SIGNAL(MethodInfo("tracks_changed")); + BIND_ENUM_CONSTANT(TYPE_VALUE); BIND_ENUM_CONSTANT(TYPE_TRANSFORM); BIND_ENUM_CONSTANT(TYPE_METHOD); @@ -2740,6 +2753,8 @@ void Animation::clear() { tracks.clear(); loop = false; length = 1; + emit_changed(); + emit_signal(SceneStringNames::get_singleton()->tracks_changed); } bool Animation::_transform_track_optimize_key(const TKey<TransformKey> &t0, const TKey<TransformKey> &t1, const TKey<TransformKey> &t2, float p_alowed_linear_err, float p_alowed_angular_err, float p_max_optimizable_angle, const Vector3 &p_norm) { diff --git a/scene/resources/bit_mask.cpp b/scene/resources/bit_map.cpp index 0e2152f244..8263096c8f 100644 --- a/scene/resources/bit_mask.cpp +++ b/scene/resources/bit_map.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* bit_mask.cpp */ +/* bit_map.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,7 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "bit_mask.h" +#include "bit_map.h" #include "core/io/image_loader.h" diff --git a/scene/resources/bit_mask.h b/scene/resources/bit_map.h index 4575064260..b3c86afd38 100644 --- a/scene/resources/bit_mask.h +++ b/scene/resources/bit_map.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* bit_mask.h */ +/* bit_map.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef BIT_MASK_H -#define BIT_MASK_H +#ifndef BIT_MAP_H +#define BIT_MAP_H #include "core/image.h" #include "core/io/resource_loader.h" @@ -72,4 +72,4 @@ public: BitMap(); }; -#endif // BIT_MASK_H +#endif // BIT_MAP_H diff --git a/scene/resources/bounds.cpp b/scene/resources/bounds.cpp deleted file mode 100644 index e6fa5b818d..0000000000 --- a/scene/resources/bounds.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/*************************************************************************/ -/* bounds.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "bounds.h" - -void Bounds::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_bsp_tree", "bsp_tree"), &Bounds::set_bsp_tree); - ClassDB::bind_method(D_METHOD("get_bsp_tree"), &Bounds::get_bsp_tree); - - ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "bsp_tree"), "set_bsp_tree", "get_bsp_tree"); -} - -void Bounds::set_bsp_tree(const BSP_Tree &p_bsp_tree) { - - bsp_tree = p_bsp_tree; -} - -BSP_Tree Bounds::get_bsp_tree() const { - - return bsp_tree; -} - -Bounds::Bounds() { -} diff --git a/scene/resources/bounds.h b/scene/resources/bounds.h deleted file mode 100644 index 9a1801f23d..0000000000 --- a/scene/resources/bounds.h +++ /dev/null @@ -1,52 +0,0 @@ -/*************************************************************************/ -/* bounds.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef BOUNDS_H -#define BOUNDS_H - -#include "core/math/bsp_tree.h" -#include "core/resource.h" - -class Bounds : public Resource { - - GDCLASS(Bounds, Resource); - BSP_Tree bsp_tree; - -protected: - static void _bind_methods(); - -public: - void set_bsp_tree(const BSP_Tree &p_bsp_tree); - BSP_Tree get_bsp_tree() const; - - Bounds(); -}; - -#endif // BOUNDS_H diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp index 7ed51a2f8f..c7a815d8a4 100644 --- a/scene/resources/default_theme/default_theme.cpp +++ b/scene/resources/default_theme/default_theme.cpp @@ -682,6 +682,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_stylebox("tab_fg", "TabContainer", sb_expand(make_stylebox(tab_current_png, 4, 4, 4, 1, 16, 4, 16, 4), 2, 2, 2, 2)); theme->set_stylebox("tab_bg", "TabContainer", sb_expand(make_stylebox(tab_behind_png, 5, 5, 5, 1, 16, 6, 16, 4), 3, 0, 3, 3)); + theme->set_stylebox("tab_disabled", "TabContainer", sb_expand(make_stylebox(tab_disabled_png, 5, 5, 5, 1, 16, 6, 16, 4), 3, 0, 3, 3)); theme->set_stylebox("panel", "TabContainer", tc_sb); theme->set_icon("increment", "TabContainer", make_icon(scroll_button_right_png)); @@ -707,6 +708,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_stylebox("tab_fg", "Tabs", sb_expand(make_stylebox(tab_current_png, 4, 3, 4, 1, 16, 3, 16, 2), 2, 2, 2, 2)); theme->set_stylebox("tab_bg", "Tabs", sb_expand(make_stylebox(tab_behind_png, 5, 4, 5, 1, 16, 5, 16, 2), 3, 3, 3, 3)); + theme->set_stylebox("tab_disabled", "Tabs", sb_expand(make_stylebox(tab_disabled_png, 5, 5, 5, 1, 16, 6, 16, 4), 3, 0, 3, 3)); theme->set_stylebox("panel", "Tabs", tc_sb); theme->set_stylebox("button_pressed", "Tabs", make_stylebox(button_pressed_png, 4, 4, 4, 4)); theme->set_stylebox("button", "Tabs", make_stylebox(button_normal_png, 4, 4, 4, 4)); diff --git a/scene/resources/default_theme/tab_disabled.png b/scene/resources/default_theme/tab_disabled.png Binary files differnew file mode 100644 index 0000000000..97157a58dd --- /dev/null +++ b/scene/resources/default_theme/tab_disabled.png diff --git a/scene/resources/default_theme/theme_data.h b/scene/resources/default_theme/theme_data.h index 353e7eddbe..2b251e5f81 100644 --- a/scene/resources/default_theme/theme_data.h +++ b/scene/resources/default_theme/theme_data.h @@ -71,7 +71,7 @@ static const unsigned char dropdown_png[] = { }; static const unsigned char error_icon_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x20, 0x8, 0x4, 0x0, 0x0, 0x0, 0xd9, 0x73, 0xb2, 0x7f, 0x0, 0x0, 0x0, 0x36, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0xa0, 0x36, 0x18, 0x5, 0xa3, 0x60, 0x14, 0xfc, 0x87, 0x40, 0x38, 0xb, 0x21, 0x6, 0x6, 0x18, 0x62, 0x98, 0x6, 0xa0, 0xb1, 0xfe, 0xe3, 0x67, 0xd1, 0xc2, 0x0, 0x10, 0xc4, 0xc5, 0x82, 0x91, 0x43, 0xc0, 0xb, 0xb8, 0x15, 0x63, 0x78, 0x6, 0x5, 0x8c, 0x82, 0x51, 0x30, 0xa, 0x0, 0x35, 0xa3, 0x4c, 0xb4, 0x7c, 0x8a, 0x7, 0x6, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x4, 0x0, 0x0, 0x0, 0xb5, 0xfa, 0x37, 0xea, 0x0, 0x0, 0x0, 0x2, 0x62, 0x4b, 0x47, 0x44, 0x0, 0xff, 0x87, 0x8f, 0xcc, 0xbf, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe2, 0xb, 0xf, 0x0, 0x22, 0x18, 0xc, 0x35, 0xef, 0x18, 0x0, 0x0, 0x0, 0xe, 0x49, 0x44, 0x41, 0x54, 0x28, 0xcf, 0x63, 0x60, 0x18, 0x5, 0xa3, 0x0, 0x1, 0x0, 0x2, 0x10, 0x0, 0x1, 0x14, 0xc2, 0xc0, 0x92, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; static const unsigned char focus_png[] = { @@ -386,6 +386,10 @@ static const unsigned char tab_current_png[] = { 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x2d, 0xf, 0x53, 0x0, 0x0, 0x0, 0x99, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0x3d, 0x48, 0x5b, 0x58, 0x66, 0x5b, 0x57, 0x65, 0x57, 0x54, 0x62, 0x55, 0x53, 0x62, 0x4a, 0x46, 0x52, 0x46, 0x41, 0x4e, 0x45, 0x41, 0x4d, 0x55, 0x52, 0x60, 0x44, 0x41, 0x4c, 0x53, 0x50, 0x5e, 0x43, 0x40, 0x4b, 0x52, 0x4e, 0x5d, 0x41, 0x3e, 0x4a, 0x4f, 0x4d, 0x5a, 0x3f, 0x3d, 0x48, 0x4e, 0x4b, 0x59, 0x3e, 0x3c, 0x47, 0x4d, 0x4a, 0x58, 0x3d, 0x3b, 0x46, 0x4b, 0x49, 0x54, 0x3c, 0x3a, 0x44, 0x4b, 0x47, 0x54, 0x3b, 0x39, 0x43, 0x3b, 0x39, 0x42, 0x3b, 0x38, 0x43, 0x3b, 0x38, 0x42, 0x3a, 0x37, 0x41, 0x39, 0x37, 0x41, 0x3a, 0x38, 0x41, 0x39, 0x36, 0x3f, 0x38, 0x36, 0x3f, 0x39, 0x36, 0x40, 0x38, 0x36, 0x40, 0x37, 0x35, 0x3e, 0x37, 0x34, 0x3e, 0x36, 0x35, 0x3d, 0xd7, 0x41, 0xa4, 0x19, 0x0, 0x0, 0x0, 0x11, 0x74, 0x52, 0x4e, 0x53, 0x4, 0xa, 0x11, 0x19, 0x1f, 0x22, 0x24, 0x15, 0x25, 0x34, 0x3f, 0x46, 0x47, 0x48, 0x77, 0xef, 0xef, 0xa3, 0x31, 0x6b, 0xc2, 0x0, 0x0, 0x0, 0x60, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x55, 0xca, 0x85, 0xd, 0xc0, 0x40, 0x14, 0xc3, 0x50, 0x27, 0xf7, 0xd5, 0xfd, 0xd7, 0x2d, 0xa6, 0x4c, 0x16, 0x3f, 0xb9, 0xd0, 0x11, 0x90, 0xa3, 0x52, 0x77, 0x49, 0x8e, 0x86, 0xd2, 0x26, 0x16, 0x7b, 0x59, 0x32, 0x68, 0x3, 0x37, 0x5d, 0xe0, 0x59, 0x3b, 0x74, 0x31, 0x67, 0x4b, 0x3b, 0xf, 0x71, 0xe5, 0xe8, 0xf, 0xec, 0xc0, 0x1f, 0x28, 0xf8, 0x2, 0x14, 0xf9, 0x42, 0xa8, 0xfc, 0x21, 0x3b, 0xe4, 0x1, 0x6f, 0x0, 0x18, 0x11, 0xac, 0x99, 0xc0, 0xe, 0x25, 0x22, 0x2d, 0x76, 0xc6, 0x13, 0x1a, 0x8, 0xac, 0x78, 0xfc, 0x1c, 0x70, 0x30, 0x2b, 0xba, 0xe9, 0x31, 0x70, 0xc1, 0x7f, 0x3b, 0x77, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; +static const unsigned char tab_disabled_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x4, 0x0, 0x0, 0x0, 0xb5, 0xfa, 0x37, 0xea, 0x0, 0x0, 0x3, 0xa7, 0x7a, 0x54, 0x58, 0x74, 0x52, 0x61, 0x77, 0x20, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x65, 0x78, 0x69, 0x66, 0x0, 0x0, 0x78, 0xda, 0xcd, 0x96, 0x59, 0x92, 0xe3, 0x2a, 0x10, 0x45, 0xff, 0x59, 0x45, 0x2f, 0x81, 0xcc, 0x24, 0x19, 0x96, 0x83, 0x18, 0x22, 0x7a, 0x7, 0x6f, 0xf9, 0x7d, 0xc1, 0x48, 0x1e, 0xab, 0x5c, 0x65, 0xfb, 0xe3, 0x89, 0xb0, 0x40, 0x29, 0x48, 0xae, 0xee, 0x41, 0xc8, 0xa6, 0xfd, 0xf7, 0xb7, 0x9b, 0x3f, 0x38, 0x28, 0x45, 0x6f, 0x9c, 0x86, 0xe8, 0x93, 0xf7, 0x16, 0x87, 0x4b, 0x2e, 0x71, 0x46, 0x23, 0xda, 0xd3, 0x71, 0xaa, 0xc9, 0xba, 0x79, 0x5e, 0x17, 0x76, 0x6f, 0x5c, 0xc5, 0xcd, 0x71, 0x83, 0x11, 0x12, 0xd4, 0x72, 0xba, 0xf4, 0x6d, 0xf5, 0xcf, 0x88, 0xeb, 0x79, 0x40, 0x70, 0x2b, 0xbe, 0x5d, 0xc7, 0x4d, 0x28, 0x2b, 0x4f, 0x5c, 0x89, 0xe8, 0x48, 0x3c, 0xf, 0x19, 0x33, 0x8f, 0xf6, 0xea, 0x17, 0x57, 0x22, 0xe1, 0x53, 0x9c, 0xd6, 0xb5, 0x49, 0x6b, 0x5c, 0x76, 0x17, 0x8f, 0xb3, 0x7e, 0x5c, 0x56, 0xda, 0x95, 0xfc, 0xf6, 0xda, 0x5, 0x98, 0x51, 0x15, 0xf9, 0x84, 0xd, 0x37, 0x21, 0xb1, 0x38, 0xc7, 0x31, 0x8b, 0x40, 0x81, 0x24, 0xc9, 0x32, 0xda, 0x79, 0xde, 0x19, 0x91, 0x80, 0xb6, 0x43, 0x9d, 0x45, 0x84, 0x1e, 0x7b, 0x67, 0x8e, 0xe6, 0x8d, 0x79, 0x47, 0xeb, 0xc6, 0x3b, 0x9b, 0x57, 0x5c, 0xae, 0xad, 0x30, 0xd6, 0xaf, 0xe, 0xfe, 0xc6, 0xa3, 0x15, 0x27, 0xbd, 0x89, 0xcb, 0x31, 0xd, 0xdf, 0x52, 0xdb, 0x67, 0xbe, 0xba, 0x91, 0xcb, 0x31, 0xc5, 0x9d, 0x77, 0xbd, 0xd7, 0xd8, 0x7b, 0x3b, 0x3d, 0x5d, 0x76, 0x1e, 0x4e, 0x79, 0xb3, 0x1e, 0x6a, 0x7f, 0x94, 0xd9, 0x42, 0xc7, 0xd, 0x56, 0xca, 0x1c, 0xe6, 0x51, 0x2, 0x7e, 0x8a, 0x76, 0x98, 0x25, 0xa1, 0x44, 0x3c, 0x62, 0x1, 0xb1, 0xa, 0x9a, 0x1b, 0x4a, 0x31, 0x94, 0x88, 0xe1, 0x69, 0x27, 0x47, 0x95, 0x32, 0x75, 0x6a, 0xb3, 0x2e, 0x54, 0x20, 0xd1, 0x71, 0xe3, 0x80, 0x9a, 0xb9, 0xb0, 0xcc, 0x58, 0x94, 0xc0, 0x89, 0xcb, 0x84, 0xe2, 0x46, 0xa1, 0xce, 0x1, 0x78, 0xaa, 0x91, 0x8, 0x3e, 0x5, 0xd4, 0x4, 0x61, 0x3e, 0xb4, 0xd0, 0x9c, 0x37, 0xcd, 0xf9, 0xa, 0x45, 0xcc, 0x5c, 0x9, 0x3d, 0x99, 0x90, 0x8c, 0x30, 0xe2, 0xae, 0x98, 0x47, 0xc1, 0x57, 0xca, 0x91, 0xa8, 0xf7, 0xb1, 0x74, 0x89, 0x6c, 0x3c, 0xbc, 0x82, 0x2e, 0x1e, 0x6b, 0x1a, 0x32, 0x6, 0xb9, 0x71, 0x46, 0x2f, 0x0, 0xa1, 0xbe, 0x3c, 0xd5, 0xe9, 0xef, 0x2c, 0xe6, 0x62, 0xdd, 0xd8, 0xb, 0xb0, 0x2, 0x82, 0x3a, 0x6d, 0x8e, 0x78, 0xc0, 0x6c, 0xb7, 0x53, 0x8a, 0x4d, 0xe9, 0xbc, 0xb6, 0x64, 0x72, 0x16, 0xf4, 0x53, 0xeb, 0x8c, 0x3d, 0xbd, 0x1a, 0x14, 0xea, 0x4a, 0x0, 0x8b, 0x30, 0xb7, 0x42, 0xc, 0x9, 0x8, 0x58, 0x4f, 0xa2, 0xe4, 0xc9, 0x6, 0xe6, 0x40, 0x4, 0x1f, 0x23, 0xf8, 0x64, 0x28, 0x67, 0x71, 0xbc, 0x81, 0x0, 0xa9, 0x72, 0x25, 0xd3, 0xc1, 0x46, 0xc4, 0x3, 0x4e, 0xe4, 0x31, 0x37, 0xc6, 0x4, 0x9a, 0x7d, 0x59, 0xf9, 0x14, 0xc6, 0xd6, 0x2, 0x10, 0x2a, 0x1e, 0xaf, 0x4a, 0x1c, 0x2f, 0x10, 0x60, 0x39, 0xa7, 0x58, 0x3f, 0xc1, 0x45, 0xac, 0xa1, 0xac, 0xa2, 0xce, 0xa8, 0xaa, 0xd7, 0xa0, 0x51, 0x93, 0x66, 0x2f, 0xde, 0x79, 0xf5, 0xde, 0x7, 0x3f, 0xf6, 0xa8, 0x1c, 0x24, 0xb8, 0xa0, 0xc1, 0x87, 0x10, 0x62, 0x48, 0x21, 0x47, 0x89, 0x2e, 0x6a, 0xf4, 0x31, 0xc4, 0x18, 0x53, 0xcc, 0x89, 0x93, 0x60, 0xb, 0xd3, 0xe4, 0x53, 0x30, 0x29, 0xa6, 0x94, 0x72, 0xc6, 0xa4, 0x19, 0xa9, 0x33, 0x46, 0x67, 0xf4, 0xc8, 0x79, 0xe3, 0x4d, 0x36, 0xb7, 0xe9, 0xe6, 0xb7, 0xb0, 0xc5, 0x2d, 0x6d, 0xb9, 0x60, 0xf9, 0x14, 0x57, 0xb4, 0xf8, 0x12, 0x4a, 0x2c, 0xa9, 0xe4, 0xca, 0x55, 0x2a, 0x5e, 0xff, 0xea, 0x6b, 0x30, 0x35, 0xd6, 0x54, 0x73, 0xa3, 0x86, 0xa5, 0xd4, 0x5c, 0xd3, 0xe6, 0x5b, 0x68, 0xb1, 0xa5, 0x96, 0x3b, 0xd6, 0x5a, 0x97, 0xee, 0xba, 0x76, 0xdf, 0x43, 0x8f, 0x3d, 0xf5, 0x7c, 0x50, 0x5b, 0x54, 0xaf, 0xa9, 0xd1, 0xd, 0xb9, 0xef, 0xa9, 0xd1, 0xa2, 0x36, 0x88, 0xb9, 0xd9, 0x2f, 0x9c, 0xa9, 0x21, 0x1c, 0xc2, 0x9e, 0x82, 0xc6, 0x76, 0xa2, 0x83, 0x19, 0x88, 0xb1, 0x23, 0x10, 0xf, 0x83, 0x0, 0x16, 0x34, 0xf, 0x66, 0x36, 0x92, 0x73, 0x3c, 0xc8, 0xd, 0x66, 0x36, 0x31, 0x5e, 0xa, 0x65, 0x50, 0x23, 0x1d, 0x70, 0x2a, 0xd, 0x62, 0x20, 0xe8, 0x1a, 0xb1, 0x76, 0x3a, 0xd8, 0x9d, 0xc9, 0x7d, 0xcb, 0xcd, 0xa8, 0xfb, 0x15, 0x37, 0xfe, 0x8a, 0x9c, 0x19, 0xe8, 0x3e, 0x41, 0xce, 0xc, 0x74, 0x8b, 0xdc, 0x3d, 0xb7, 0x7, 0xd4, 0x6a, 0x9e, 0x5f, 0x14, 0x99, 0x80, 0xc6, 0x5b, 0x38, 0x3c, 0xb5, 0xd2, 0xb1, 0xb1, 0xa1, 0x43, 0x8b, 0x99, 0x63, 0x1e, 0xdf, 0xa4, 0x97, 0x6b, 0xf3, 0x6e, 0x82, 0xff, 0x59, 0xa2, 0x76, 0x98, 0x52, 0xcd, 0x96, 0x67, 0xd4, 0xe2, 0x7b, 0x78, 0x6a, 0xd8, 0xd7, 0x6a, 0x83, 0x5d, 0x64, 0x45, 0x84, 0x8e, 0x89, 0x9e, 0x4a, 0xe9, 0x9a, 0xf6, 0x51, 0x92, 0x67, 0xc, 0xd4, 0xe2, 0x2e, 0xcf, 0xfd, 0x52, 0xb, 0xf9, 0x35, 0x30, 0x1d, 0x1e, 0xe1, 0x3, 0xb4, 0xf2, 0x97, 0x94, 0x9f, 0x8a, 0x71, 0x37, 0x62, 0x3e, 0x48, 0xd, 0x42, 0xcc, 0xae, 0x24, 0xb7, 0xa7, 0x4a, 0xf8, 0x50, 0xd2, 0x3e, 0x8d, 0xbf, 0xda, 0xc3, 0x12, 0xb3, 0xf9, 0xa7, 0x4a, 0xe8, 0x91, 0x27, 0x9f, 0x51, 0x74, 0x1, 0x67, 0x5b, 0xc9, 0xcd, 0xd7, 0x4a, 0x5c, 0xff, 0xce, 0x93, 0xf7, 0x14, 0x5d, 0x78, 0x52, 0x6e, 0xee, 0x99, 0x7, 0x4a, 0xea, 0xfe, 0xd6, 0x44, 0x25, 0xa7, 0xe3, 0x6f, 0xeb, 0xf, 0x6a, 0xf3, 0x93, 0x8e, 0x14, 0xf6, 0x67, 0xeb, 0xc2, 0x5f, 0x2c, 0x73, 0x73, 0x88, 0xad, 0xb2, 0x6b, 0xca, 0x73, 0xb8, 0x8e, 0xff, 0xd0, 0x3f, 0xaf, 0xcd, 0x77, 0x1d, 0xb4, 0x9f, 0x2d, 0x79, 0xe6, 0xb7, 0xe9, 0x2e, 0xbf, 0x62, 0xc9, 0x5d, 0x6d, 0x9e, 0x58, 0xa2, 0x4f, 0x76, 0x0, 0xa9, 0xec, 0xf7, 0x6d, 0xe4, 0x25, 0x4b, 0xee, 0x6a, 0xf3, 0xd8, 0x92, 0xfa, 0x74, 0x33, 0x71, 0xe9, 0x7a, 0xb9, 0x9a, 0xcf, 0x6c, 0xfd, 0xa7, 0x44, 0x17, 0xeb, 0xf5, 0xf7, 0x4a, 0x2e, 0x13, 0xbd, 0xbd, 0xad, 0xd9, 0x99, 0xe8, 0x4d, 0x25, 0x9f, 0x50, 0x74, 0x65, 0x89, 0x79, 0x57, 0xc9, 0x3b, 0x8a, 0x1e, 0xc2, 0xd9, 0x15, 0x75, 0xfc, 0x61, 0x49, 0xe6, 0x1f, 0xbf, 0x1c, 0xa8, 0x52, 0x2b, 0xb1, 0xc9, 0xd4, 0x0, 0x0, 0x0, 0x2, 0x62, 0x4b, 0x47, 0x44, 0x0, 0xff, 0x87, 0x8f, 0xcc, 0xbf, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0x2e, 0x23, 0x0, 0x0, 0x2e, 0x23, 0x1, 0x78, 0xa5, 0x3f, 0x76, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe3, 0x2, 0xa, 0x13, 0x29, 0x21, 0x5f, 0x36, 0xe2, 0x14, 0x0, 0x0, 0x0, 0xaf, 0x49, 0x44, 0x41, 0x54, 0x28, 0xcf, 0x7d, 0x91, 0x41, 0xa, 0xc2, 0x40, 0x10, 0x4, 0x6b, 0x92, 0x61, 0x37, 0xb0, 0x87, 0xec, 0x39, 0x3e, 0xc6, 0x3f, 0xf8, 0x9a, 0x3c, 0xc1, 0xd7, 0xf8, 0x3, 0xf, 0x3e, 0xc6, 0xab, 0x44, 0x50, 0x30, 0x26, 0x66, 0x3c, 0x2c, 0x6, 0x3, 0xd9, 0xf4, 0x69, 0xa0, 0xab, 0x9b, 0x86, 0x11, 0x14, 0x87, 0xa7, 0xc2, 0x51, 0x52, 0x90, 0x34, 0xf1, 0xe1, 0xcd, 0x8b, 0x9e, 0xb7, 0xe2, 0x8, 0x44, 0x6a, 0x2, 0x1e, 0x41, 0x0, 0xc3, 0xe8, 0x79, 0x72, 0xa7, 0x3, 0xc5, 0x13, 0xf7, 0x87, 0x5d, 0x3b, 0x46, 0x16, 0xd2, 0xee, 0x7a, 0xbc, 0x9c, 0x18, 0x95, 0x8a, 0xba, 0x69, 0x6f, 0x71, 0xc4, 0xfe, 0x6c, 0x41, 0x63, 0xd3, 0x72, 0xe6, 0xa1, 0x38, 0xc2, 0x10, 0x87, 0x65, 0x1c, 0x63, 0x60, 0x88, 0x4, 0x9c, 0x52, 0xe2, 0xa7, 0x45, 0x9a, 0x79, 0x29, 0x9e, 0x52, 0x29, 0x10, 0x63, 0x5a, 0x1, 0xc, 0x84, 0x42, 0x1, 0xc9, 0x36, 0x8, 0x68, 0x3a, 0x33, 0x0, 0x9, 0x30, 0x5b, 0x5, 0xc, 0x6c, 0x6e, 0x98, 0x36, 0x1b, 0x24, 0xdb, 0xf0, 0xdb, 0xc0, 0x2a, 0x90, 0x54, 0x6c, 0xba, 0x96, 0x0, 0xc9, 0x2, 0xc2, 0xfc, 0xe0, 0xac, 0xbe, 0xe, 0x38, 0x38, 0x83, 0xbf, 0x35, 0x30, 0x94, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 +}; + static const unsigned char tab_menu_png[] = { 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x4, 0x0, 0x0, 0x0, 0xb5, 0xfa, 0x37, 0xea, 0x0, 0x0, 0x0, 0x36, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x40, 0x5, 0xa3, 0xe0, 0xc1, 0x7f, 0x54, 0x48, 0x3, 0x5, 0xf, 0xe3, 0x1e, 0x7c, 0x81, 0x4b, 0x7f, 0x7b, 0x98, 0x86, 0xc5, 0x15, 0xf7, 0x35, 0xee, 0x5f, 0x2, 0x4b, 0x5f, 0x7f, 0xac, 0x8b, 0xc3, 0xa1, 0x2f, 0xb8, 0x1f, 0xce, 0x7f, 0x38, 0xff, 0x5, 0x37, 0x75, 0xbd, 0xf, 0x0, 0x52, 0xd4, 0x48, 0xb8, 0x2d, 0x78, 0x5a, 0x91, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; diff --git a/scene/resources/dynamic_font.h b/scene/resources/dynamic_font.h index 39e81ca43d..887c7b42c8 100644 --- a/scene/resources/dynamic_font.h +++ b/scene/resources/dynamic_font.h @@ -54,8 +54,9 @@ public: struct { uint32_t size : 16; uint32_t outline_size : 8; - bool mipmaps : 1; - bool filter : 1; + uint32_t mipmaps : 1; + uint32_t filter : 1; + uint32_t unused : 6; }; uint32_t key; }; diff --git a/scene/resources/environment.cpp b/scene/resources/environment.cpp index a57b7bbb42..17609ed505 100644 --- a/scene/resources/environment.cpp +++ b/scene/resources/environment.cpp @@ -303,7 +303,7 @@ Ref<Texture> Environment::get_adjustment_color_correction() const { void Environment::_validate_property(PropertyInfo &property) const { - if (property.name == "background_sky" || property.name == "background_sky_custom_fov" || property.name == "background_sky_orientation" || property.name == "ambient_light/sky_contribution") { + if (property.name == "background_sky" || property.name == "background_sky_custom_fov" || property.name == "background_sky_orientation" || property.name == "background_sky_rotation" || property.name == "background_sky_rotation_degrees" || property.name == "ambient_light/sky_contribution") { if (bg_mode != BG_SKY && bg_mode != BG_COLOR_SKY) { property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; } @@ -1291,7 +1291,14 @@ void Environment::_bind_methods() { BIND_ENUM_CONSTANT(SSAO_QUALITY_HIGH); } -Environment::Environment() { +Environment::Environment() : + bg_mode(BG_CLEAR_COLOR), + tone_mapper(TONE_MAPPER_LINEAR), + ssao_blur(SSAO_BLUR_DISABLED), + ssao_quality(SSAO_QUALITY_LOW), + glow_blend_mode(GLOW_BLEND_MODE_ADDITIVE), + dof_blur_far_quality(DOF_BLUR_QUALITY_LOW), + dof_blur_near_quality(DOF_BLUR_QUALITY_LOW) { environment = VS::get_singleton()->environment_create(); diff --git a/scene/resources/environment.h b/scene/resources/environment.h index 666112b473..a54f13a88f 100644 --- a/scene/resources/environment.h +++ b/scene/resources/environment.h @@ -32,7 +32,7 @@ #define ENVIRONMENT_H #include "core/resource.h" -#include "scene/resources/sky_box.h" +#include "scene/resources/sky.h" #include "scene/resources/texture.h" #include "servers/visual_server.h" diff --git a/scene/resources/color_ramp.cpp b/scene/resources/gradient.cpp index 845a1474a4..99ce8ef821 100644 --- a/scene/resources/color_ramp.cpp +++ b/scene/resources/gradient.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* color_ramp.cpp */ +/* gradient.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,7 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "color_ramp.h" +#include "gradient.h" + #include "core/core_string_names.h" //setter and getter names for property serialization diff --git a/scene/resources/color_ramp.h b/scene/resources/gradient.h index 7a96bb429b..a51a0ca0d0 100644 --- a/scene/resources/color_ramp.h +++ b/scene/resources/gradient.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* color_ramp.h */ +/* gradient.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef SCENE_RESOURCES_COLOR_RAMP_H_ -#define SCENE_RESOURCES_COLOR_RAMP_H_ +#ifndef GRADIENT_H +#define GRADIENT_H #include "core/resource.h" @@ -126,4 +126,4 @@ public: int get_points_count() const; }; -#endif /* SCENE_RESOURCES_COLOR_RAMP_H_ */ +#endif // GRADIENT_H diff --git a/scene/resources/shape_line_2d.cpp b/scene/resources/line_shape_2d.cpp index 4ca535658f..f5d5fb561a 100644 --- a/scene/resources/shape_line_2d.cpp +++ b/scene/resources/line_shape_2d.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* shape_line_2d.cpp */ +/* line_shape_2d.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,7 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "shape_line_2d.h" +#include "line_shape_2d.h" + #include "servers/physics_2d_server.h" #include "servers/visual_server.h" diff --git a/scene/resources/shape_line_2d.h b/scene/resources/line_shape_2d.h index dd3dbe3a43..f684862025 100644 --- a/scene/resources/shape_line_2d.h +++ b/scene/resources/line_shape_2d.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* shape_line_2d.h */ +/* line_shape_2d.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef SHAPE_LINE_2D_H -#define SHAPE_LINE_2D_H +#ifndef LINE_SHAPE_2D_H +#define LINE_SHAPE_2D_H #include "scene/resources/shape_2d.h" @@ -59,4 +59,4 @@ public: LineShape2D(); }; -#endif // SHAPE_LINE_2D_H +#endif // LINE_SHAPE_2D_H diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp index 5ffaf41581..190dc707c4 100644 --- a/scene/resources/material.cpp +++ b/scene/resources/material.cpp @@ -617,11 +617,17 @@ void SpatialMaterial::_update_shader() { code += "\tMODELVIEW_MATRIX = INV_CAMERA_MATRIX * mat_world;\n"; //handle animation + code += "\tfloat h_frames = float(particles_anim_h_frames);\n"; + code += "\tfloat v_frames = float(particles_anim_v_frames);\n"; code += "\tfloat particle_total_frames = float(particles_anim_h_frames * particles_anim_v_frames);\n"; code += "\tfloat particle_frame = floor(INSTANCE_CUSTOM.z * float(particle_total_frames));\n"; - code += "\tif (!particles_anim_loop) particle_frame=clamp(particle_frame,0.0,particle_total_frames-1.0); else particle_frame=mod(particle_frame,float(particle_total_frames));\n"; - code += "\tUV /= vec2(float(particles_anim_h_frames),float(particles_anim_v_frames));\n"; - code += "\tUV += vec2(mod(particle_frame,float(particles_anim_h_frames)) / float(particles_anim_h_frames), floor(particle_frame / float(particles_anim_h_frames)) / float(particles_anim_v_frames));\n"; + code += "\tif (!particles_anim_loop) {\n"; + code += "\t\tparticle_frame = clamp(particle_frame, 0.0, particle_total_frames - 1.0);\n"; + code += "\t} else {\n"; + code += "\t\tparticle_frame = mod(particle_frame, particle_total_frames);\n"; + code += "\t}"; + code += "\tUV /= vec2(h_frames, v_frames);\n"; + code += "\tUV += vec2(mod(particle_frame, h_frames) / h_frames, floor(particle_frame / h_frames) / v_frames);\n"; } break; } @@ -824,7 +830,7 @@ void SpatialMaterial::_update_shader() { code += "\tALPHA = albedo.a * albedo_tex.a;\n"; } - if (!VisualServer::get_singleton()->is_low_end() && proximity_fade_enabled) { + if (proximity_fade_enabled) { code += "\tfloat depth_tex = textureLod(DEPTH_TEXTURE,SCREEN_UV,0.0).r;\n"; code += "\tvec4 world_pos = INV_PROJECTION_MATRIX * vec4(SCREEN_UV*2.0-1.0,depth_tex*2.0-1.0,1.0);\n"; code += "\tworld_pos.xyz/=world_pos.w;\n"; diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp index 805d30245a..98402dbeaf 100644 --- a/scene/resources/mesh.cpp +++ b/scene/resources/mesh.cpp @@ -84,15 +84,15 @@ Ref<TriangleMesh> Mesh::generate_triangle_mesh() const { PoolVector<int> indices = a[ARRAY_INDEX]; PoolVector<int>::Read ir = indices.read(); - for (int i = 0; i < ic; i++) { - int index = ir[i]; + for (int j = 0; j < ic; j++) { + int index = ir[j]; facesw[widx++] = vr[index]; } } else { - for (int i = 0; i < vc; i++) - facesw[widx++] = vr[i]; + for (int j = 0; j < vc; j++) + facesw[widx++] = vr[j]; } } @@ -787,7 +787,6 @@ void ArrayMesh::add_surface_from_arrays(PrimitiveType p_primitive, const Array & Surface s; VisualServer::get_singleton()->mesh_add_surface_from_arrays(mesh, (VisualServer::PrimitiveType)p_primitive, p_arrays, p_blend_shapes, p_flags); - surfaces.push_back(s); /* make aABB? */ { @@ -808,8 +807,9 @@ void ArrayMesh::add_surface_from_arrays(PrimitiveType p_primitive, const Array & aabb.expand_to(vtx[i]); } - surfaces.write[surfaces.size() - 1].aabb = aabb; - surfaces.write[surfaces.size() - 1].is_2d = arr.get_type() == Variant::POOL_VECTOR2_ARRAY; + s.aabb = aabb; + s.is_2d = arr.get_type() == Variant::POOL_VECTOR2_ARRAY; + surfaces.push_back(s); _recompute_aabb(); } diff --git a/scene/resources/multimesh.cpp b/scene/resources/multimesh.cpp index 7084c3b4e1..1b406551ab 100644 --- a/scene/resources/multimesh.cpp +++ b/scene/resources/multimesh.cpp @@ -166,11 +166,22 @@ void MultiMesh::set_instance_transform(int p_instance, const Transform &p_transf VisualServer::get_singleton()->multimesh_instance_set_transform(multimesh, p_instance, p_transform); } + +void MultiMesh::set_instance_transform_2d(int p_instance, const Transform2D &p_transform) { + + VisualServer::get_singleton()->multimesh_instance_set_transform_2d(multimesh, p_instance, p_transform); +} + Transform MultiMesh::get_instance_transform(int p_instance) const { return VisualServer::get_singleton()->multimesh_instance_get_transform(multimesh, p_instance); } +Transform2D MultiMesh::get_instance_transform_2d(int p_instance) const { + + return VisualServer::get_singleton()->multimesh_instance_get_transform_2d(multimesh, p_instance); +} + void MultiMesh::set_instance_color(int p_instance, const Color &p_color) { VisualServer::get_singleton()->multimesh_instance_set_color(multimesh, p_instance, p_color); @@ -245,7 +256,9 @@ void MultiMesh::_bind_methods() { ClassDB::bind_method(D_METHOD("set_instance_count", "count"), &MultiMesh::set_instance_count); ClassDB::bind_method(D_METHOD("get_instance_count"), &MultiMesh::get_instance_count); ClassDB::bind_method(D_METHOD("set_instance_transform", "instance", "transform"), &MultiMesh::set_instance_transform); + ClassDB::bind_method(D_METHOD("set_instance_transform_2d", "instance", "transform"), &MultiMesh::set_instance_transform_2d); ClassDB::bind_method(D_METHOD("get_instance_transform", "instance"), &MultiMesh::get_instance_transform); + ClassDB::bind_method(D_METHOD("get_instance_transform_2d", "instance"), &MultiMesh::get_instance_transform_2d); ClassDB::bind_method(D_METHOD("set_instance_color", "instance", "color"), &MultiMesh::set_instance_color); ClassDB::bind_method(D_METHOD("get_instance_color", "instance"), &MultiMesh::get_instance_color); ClassDB::bind_method(D_METHOD("set_instance_custom_data", "instance", "custom_data"), &MultiMesh::set_instance_custom_data); diff --git a/scene/resources/multimesh.h b/scene/resources/multimesh.h index 4e70907399..ac2c69e022 100644 --- a/scene/resources/multimesh.h +++ b/scene/resources/multimesh.h @@ -94,7 +94,9 @@ public: int get_instance_count() const; void set_instance_transform(int p_instance, const Transform &p_transform); + void set_instance_transform_2d(int p_instance, const Transform2D &p_transform); Transform get_instance_transform(int p_instance) const; + Transform2D get_instance_transform_2d(int p_instance) const; void set_instance_color(int p_instance, const Color &p_color); Color get_instance_color(int p_instance) const; diff --git a/scene/resources/packed_scene.cpp b/scene/resources/packed_scene.cpp index ea810edf8c..0d12d388ef 100644 --- a/scene/resources/packed_scene.cpp +++ b/scene/resources/packed_scene.cpp @@ -55,7 +55,7 @@ Node *SceneState::instance(GenEditState p_edit_state) const { Node *p_name; \ if (p_id & FLAG_ID_IS_PATH) { \ NodePath np = node_paths[p_id & FLAG_MASK]; \ - p_name = ret_nodes[0]->_get_node(np); \ + p_name = ret_nodes[0]->get_node_or_null(np); \ } else { \ ERR_FAIL_INDEX_V(p_id &FLAG_MASK, nc, NULL); \ p_name = ret_nodes[p_id & FLAG_MASK]; \ @@ -236,8 +236,8 @@ Node *SceneState::instance(GenEditState p_edit_state) const { } else { //for instances, a copy must be made - Node *base = i == 0 ? node : ret_nodes[0]; - Ref<Resource> local_dupe = res->duplicate_for_local_scene(base, resources_local_to_scene); + Node *base2 = i == 0 ? node : ret_nodes[0]; + Ref<Resource> local_dupe = res->duplicate_for_local_scene(base2, resources_local_to_scene); resources_local_to_scene[res] = local_dupe; res = local_dupe; value = local_dupe; @@ -296,8 +296,8 @@ Node *SceneState::instance(GenEditState p_edit_state) const { ret_nodes[i] = node; if (node && gen_node_path_cache && ret_nodes[0]) { - NodePath n = ret_nodes[0]->get_path_to(node); - node_path_cache[n] = i; + NodePath n2 = ret_nodes[0]->get_path_to(node); + node_path_cache[n2] = i; } } @@ -342,7 +342,7 @@ Node *SceneState::instance(GenEditState p_edit_state) const { } for (int i = 0; i < editable_instances.size(); i++) { - Node *ei = ret_nodes[0]->_get_node(editable_instances[i]); + Node *ei = ret_nodes[0]->get_node_or_null(editable_instances[i]); if (ei) { ret_nodes[0]->set_editable_instance(ei, true); } @@ -749,7 +749,7 @@ Error SceneState::_parse_connections(Node *p_owner, Node *p_node, Map<StringName { Node *nl = p_node; - bool exists = false; + bool exists2 = false; while (nl) { @@ -763,7 +763,7 @@ Error SceneState::_parse_connections(Node *p_owner, Node *p_node, Map<StringName if (from_node >= 0 && to_node >= 0) { //this one has state for this node, save if (state->is_connection(from_node, c.signal, to_node, c.method)) { - exists = true; + exists2 = true; break; } } @@ -781,7 +781,7 @@ Error SceneState::_parse_connections(Node *p_owner, Node *p_node, Map<StringName if (from_node >= 0 && to_node >= 0) { //this one has state for this node, save if (state->is_connection(from_node, c.signal, to_node, c.method)) { - exists = true; + exists2 = true; break; } } @@ -791,7 +791,7 @@ Error SceneState::_parse_connections(Node *p_owner, Node *p_node, Map<StringName } } - if (exists) { + if (exists2) { continue; } } diff --git a/scene/resources/polygon_path_finder.cpp b/scene/resources/polygon_path_finder.cpp index a45a55a258..52fc21ac11 100644 --- a/scene/resources/polygon_path_finder.cpp +++ b/scene/resources/polygon_path_finder.cpp @@ -441,9 +441,9 @@ void PolygonPathFinder::_set_data(const Dictionary &p_data) { PoolVector<float> penalties = p_data["penalties"]; if (penalties.size() == pc) { - PoolVector<float>::Read pr = penalties.read(); + PoolVector<float>::Read pr2 = penalties.read(); for (int i = 0; i < pc; i++) { - points.write[i].penalty = pr[i]; + points.write[i].penalty = pr2[i]; } } } diff --git a/scene/resources/primitive_meshes.cpp b/scene/resources/primitive_meshes.cpp index 9ef12aa4e6..db58fe7823 100644 --- a/scene/resources/primitive_meshes.cpp +++ b/scene/resources/primitive_meshes.cpp @@ -376,17 +376,17 @@ void CapsuleMesh::_create_mesh_array(Array &p_arr) const { z = radius * cos(0.5 * Math_PI * v); for (i = 0; i <= radial_segments; i++) { - float u = i; - u /= radial_segments; + float u2 = i; + u2 /= radial_segments; - x = sin(u * (Math_PI * 2.0)); - y = -cos(u * (Math_PI * 2.0)); + x = sin(u2 * (Math_PI * 2.0)); + y = -cos(u2 * (Math_PI * 2.0)); Vector3 p = Vector3(x * radius * w, y * radius * w, z); points.push_back(p + Vector3(0.0, 0.0, -0.5 * mid_height)); normals.push_back(p.normalized()); ADD_TANGENT(-y, x, 0.0, 1.0) - uvs.push_back(Vector2(u, twothirds + ((v - 1.0) * onethird))); + uvs.push_back(Vector2(u2, twothirds + ((v - 1.0) * onethird))); point++; if (i > 0 && j > 0) { diff --git a/scene/resources/scene_format_text.cpp b/scene/resources/resource_format_text.cpp index 558810d92a..9ef6b9b474 100644 --- a/scene/resources/scene_format_text.cpp +++ b/scene/resources/resource_format_text.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* scene_format_text.cpp */ +/* resource_format_text.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,7 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "scene_format_text.h" +#include "resource_format_text.h" + #include "core/io/resource_format_binary.h" #include "core/os/dir_access.h" #include "core/project_settings.h" @@ -1407,7 +1408,20 @@ void ResourceFormatSaverTextInstance::_find_resources(const Variant &p_variant, if (pi.usage & PROPERTY_USAGE_STORAGE) { Variant v = res->get(I->get().name); - _find_resources(v); + + if (pi.usage & PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT) { + RES sres = v; + if (sres.is_valid()) { + NonPersistentKey npk; + npk.base = res; + npk.property = pi.name; + non_persistent_map[npk] = sres; + resource_set.insert(sres); + saved_resources.push_back(sres); + } + } else { + _find_resources(v); + } } I = I->next(); @@ -1562,7 +1576,7 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path, const RES &p_r break; //save as a scene if (main) { - f->store_line("[resource]\n"); + f->store_line("[resource]"); } else { String line = "[sub_resource "; if (res->get_subindex() == 0) { @@ -1577,7 +1591,7 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path, const RES &p_r int idx = res->get_subindex(); line += "type=\"" + res->get_class() + "\" id=" + itos(idx); - f->store_line(line + "]\n"); + f->store_line(line + "]"); if (takeover_paths) { res->set_path(p_path + "::" + itos(idx), true); } @@ -1599,7 +1613,17 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path, const RES &p_r if (PE->get().usage & PROPERTY_USAGE_STORAGE) { String name = PE->get().name; - Variant value = res->get(name); + Variant value; + if (PE->get().usage & PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT) { + NonPersistentKey npk; + npk.base = res; + npk.property = name; + if (non_persistent_map.has(npk)) { + value = non_persistent_map[npk]; + } + } else { + value = res->get(name); + } Variant default_value = ClassDB::class_get_default_property_value(res->get_class(), name); if (default_value.get_type() != Variant::NIL && bool(Variant::evaluate(Variant::OP_EQUAL, value, default_value))) { diff --git a/scene/resources/scene_format_text.h b/scene/resources/resource_format_text.h index 8fedbd0dd6..8d78ab33b0 100644 --- a/scene/resources/scene_format_text.h +++ b/scene/resources/resource_format_text.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* scene_format_text.h */ +/* resource_format_text.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef SCENE_FORMAT_TEXT_H -#define SCENE_FORMAT_TEXT_H +#ifndef RESOURCE_FORMAT_TEXT_H +#define RESOURCE_FORMAT_TEXT_H #include "core/io/resource_loader.h" #include "core/io/resource_saver.h" @@ -155,6 +155,15 @@ class ResourceFormatSaverTextInstance { bool bundle_resources; bool skip_editor; FileAccess *f; + + struct NonPersistentKey { //for resource properties generated on the fly + RES base; + StringName property; + bool operator<(const NonPersistentKey &p_key) const { return base == p_key.base ? property < p_key.property : base < p_key.base; } + }; + + Map<NonPersistentKey, RES> non_persistent_map; + Set<RES> resource_set; List<RES> saved_resources; Map<RES, int> external_resources; @@ -180,4 +189,4 @@ public: ResourceFormatSaverText(); }; -#endif // SCENE_FORMAT_TEXT_H +#endif // RESOURCE_FORMAT_TEXT_H diff --git a/scene/resources/sky_box.cpp b/scene/resources/sky.cpp index d9da85310e..a473fe8b7f 100644 --- a/scene/resources/sky_box.cpp +++ b/scene/resources/sky.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* sky_box.cpp */ +/* sky.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,7 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "sky_box.h" +#include "sky.h" + #include "core/io/image_loader.h" void Sky::set_radiance_size(RadianceSize p_size) { diff --git a/scene/resources/sky_box.h b/scene/resources/sky.h index af10803b36..3b410396e0 100644 --- a/scene/resources/sky_box.h +++ b/scene/resources/sky.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* sky_box.h */ +/* sky.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,11 +28,12 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef SKY_BOX_H -#define SKY_BOX_H +#ifndef SKY_H +#define SKY_H #include "core/os/thread.h" #include "scene/resources/texture.h" + class Sky : public Resource { GDCLASS(Sky, Resource); @@ -196,4 +197,4 @@ public: VARIANT_ENUM_CAST(ProceduralSky::TextureSize) -#endif // SKY_BOX_H +#endif // SKY_H diff --git a/scene/resources/surface_tool.cpp b/scene/resources/surface_tool.cpp index 2116dd0b1e..83f29503fa 100644 --- a/scene/resources/surface_tool.cpp +++ b/scene/resources/surface_tool.cpp @@ -190,10 +190,10 @@ void SurfaceTool::add_smooth_group(bool p_smooth) { } } -void SurfaceTool::add_triangle_fan(const Vector<Vector3> &p_vertexes, const Vector<Vector2> &p_uvs, const Vector<Color> &p_colors, const Vector<Vector2> &p_uv2s, const Vector<Vector3> &p_normals, const Vector<Plane> &p_tangents) { +void SurfaceTool::add_triangle_fan(const Vector<Vector3> &p_vertices, const Vector<Vector2> &p_uvs, const Vector<Color> &p_colors, const Vector<Vector2> &p_uv2s, const Vector<Vector3> &p_normals, const Vector<Plane> &p_tangents) { ERR_FAIL_COND(!begun); ERR_FAIL_COND(primitive != Mesh::PRIMITIVE_TRIANGLES); - ERR_FAIL_COND(p_vertexes.size() < 3); + ERR_FAIL_COND(p_vertices.size() < 3); #define ADD_POINT(n) \ { \ @@ -207,10 +207,10 @@ void SurfaceTool::add_triangle_fan(const Vector<Vector3> &p_vertexes, const Vect add_normal(p_normals[n]); \ if (p_tangents.size() > n) \ add_tangent(p_tangents[n]); \ - add_vertex(p_vertexes[n]); \ + add_vertex(p_vertices[n]); \ } - for (int i = 0; i < p_vertexes.size() - 2; i++) { + for (int i = 0; i < p_vertices.size() - 2; i++) { ADD_POINT(0); ADD_POINT(i + 1); ADD_POINT(i + 2); @@ -1012,7 +1012,7 @@ void SurfaceTool::_bind_methods() { ClassDB::bind_method(D_METHOD("add_weights", "weights"), &SurfaceTool::add_weights); ClassDB::bind_method(D_METHOD("add_smooth_group", "smooth"), &SurfaceTool::add_smooth_group); - ClassDB::bind_method(D_METHOD("add_triangle_fan", "vertexes", "uvs", "colors", "uv2s", "normals", "tangents"), &SurfaceTool::add_triangle_fan, DEFVAL(Vector<Vector2>()), DEFVAL(Vector<Color>()), DEFVAL(Vector<Vector2>()), DEFVAL(Vector<Vector3>()), DEFVAL(Vector<Plane>())); + ClassDB::bind_method(D_METHOD("add_triangle_fan", "vertices", "uvs", "colors", "uv2s", "normals", "tangents"), &SurfaceTool::add_triangle_fan, DEFVAL(Vector<Vector2>()), DEFVAL(Vector<Color>()), DEFVAL(Vector<Vector2>()), DEFVAL(Vector<Vector3>()), DEFVAL(Vector<Plane>())); ClassDB::bind_method(D_METHOD("add_index", "index"), &SurfaceTool::add_index); diff --git a/scene/resources/surface_tool.h b/scene/resources/surface_tool.h index ef13238c13..a3b110f0d8 100644 --- a/scene/resources/surface_tool.h +++ b/scene/resources/surface_tool.h @@ -109,7 +109,7 @@ public: void add_weights(const Vector<float> &p_weights); void add_smooth_group(bool p_smooth); - void add_triangle_fan(const Vector<Vector3> &p_vertexes, const Vector<Vector2> &p_uvs = Vector<Vector2>(), const Vector<Color> &p_colors = Vector<Color>(), const Vector<Vector2> &p_uv2s = Vector<Vector2>(), const Vector<Vector3> &p_normals = Vector<Vector3>(), const Vector<Plane> &p_tangents = Vector<Plane>()); + void add_triangle_fan(const Vector<Vector3> &p_vertices, const Vector<Vector2> &p_uvs = Vector<Vector2>(), const Vector<Color> &p_colors = Vector<Color>(), const Vector<Vector2> &p_uv2s = Vector<Vector2>(), const Vector<Vector3> &p_normals = Vector<Vector3>(), const Vector<Plane> &p_tangents = Vector<Plane>()); void add_index(int p_index); diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp index ff5900cd3e..e8cc160acf 100644 --- a/scene/resources/texture.cpp +++ b/scene/resources/texture.cpp @@ -34,7 +34,7 @@ #include "core/io/image_loader.h" #include "core/method_bind_ext.gen.inc" #include "core/os/os.h" -#include "scene/resources/bit_mask.h" +#include "scene/resources/bit_map.h" Size2 Texture::get_size() const { @@ -157,7 +157,7 @@ bool ImageTexture::_get(const StringName &p_name, Variant &r_ret) const { void ImageTexture::_get_property_list(List<PropertyInfo> *p_list) const { p_list->push_back(PropertyInfo(Variant::INT, "flags", PROPERTY_HINT_FLAGS, "Mipmaps,Repeat,Filter,Anisotropic,sRGB,Mirrored Repeat")); - p_list->push_back(PropertyInfo(Variant::OBJECT, "image", PROPERTY_HINT_RESOURCE_TYPE, "Image")); + p_list->push_back(PropertyInfo(Variant::OBJECT, "image", PROPERTY_HINT_RESOURCE_TYPE, "Image", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT)); p_list->push_back(PropertyInfo(Variant::VECTOR2, "size", PROPERTY_HINT_NONE, "")); } @@ -178,12 +178,6 @@ void ImageTexture::_reload_hook(const RID &p_hook) { _change_notify(); } -bool ImageTexture::keep_images_cached = false; - -void ImageTexture::set_keep_images_cached(bool p_enable) { - keep_images_cached = p_enable; -} - void ImageTexture::create(int p_width, int p_height, Image::Format p_format, uint32_t p_flags) { flags = p_flags; @@ -205,9 +199,7 @@ void ImageTexture::create_from_image(const Ref<Image> &p_image, uint32_t p_flags VisualServer::get_singleton()->texture_set_data(texture, p_image); _change_notify(); - if (keep_images_cached) { - image_cache = p_image; - } + image_stored = true; } void ImageTexture::set_flags(uint32_t p_flags) { @@ -255,10 +247,7 @@ void ImageTexture::set_data(const Ref<Image> &p_image) { _change_notify(); alpha_cache.unref(); - - if (keep_images_cached) { - image_cache = p_image; - } + image_stored = true; } void ImageTexture::_resource_path_changed() { @@ -268,10 +257,10 @@ void ImageTexture::_resource_path_changed() { Ref<Image> ImageTexture::get_data() const { - if (image_cache.is_valid()) { - return image_cache; - } else { + if (image_stored) { return VisualServer::get_singleton()->texture_get_data(texture); + } else { + return Ref<Image>(); } } @@ -662,16 +651,16 @@ Error StreamTexture::_load_data(const String &p_path, int &tw, int &th, int &fla int sw = tw; int sh = th; - int mipmaps = Image::get_image_required_mipmaps(tw, th, format); + int mipmaps2 = Image::get_image_required_mipmaps(tw, th, format); int total_size = Image::get_image_data_size(tw, th, format, true); int idx = 0; int ofs = 0; - while (mipmaps > 1 && p_size_limit > 0 && (sw > p_size_limit || sh > p_size_limit)) { + while (mipmaps2 > 1 && p_size_limit > 0 && (sw > p_size_limit || sh > p_size_limit)) { sw = MAX(sw >> 1, 1); sh = MAX(sh >> 1, 1); - mipmaps--; + mipmaps2--; idx++; } @@ -698,7 +687,7 @@ Error StreamTexture::_load_data(const String &p_path, int &tw, int &th, int &fla int expected = total_size - ofs; if (bytes < expected) { - //this is a compatibility workaround for older format, which saved less mipmaps. It is still recommended the image is reimported. + //this is a compatibility workaround for older format, which saved less mipmaps2. It is still recommended the image is reimported. zeromem(w.ptr() + bytes, (expected - bytes)); } else if (bytes != expected) { ERR_FAIL_V(ERR_FILE_CORRUPT); diff --git a/scene/resources/texture.h b/scene/resources/texture.h index 4b5b504510..dc3a3e0c74 100644 --- a/scene/resources/texture.h +++ b/scene/resources/texture.h @@ -37,8 +37,8 @@ #include "core/os/rw_lock.h" #include "core/os/thread_safe.h" #include "core/resource.h" -#include "scene/resources/color_ramp.h" #include "scene/resources/curve.h" +#include "scene/resources/gradient.h" #include "servers/visual_server.h" /** @@ -111,7 +111,7 @@ private: Size2 size_override; float lossy_storage_quality; mutable Ref<BitMap> alpha_cache; - Ref<Image> image_cache; + bool image_stored; protected: virtual void reload_from_file(); @@ -126,11 +126,7 @@ protected: void _set_data(Dictionary p_data); - static bool keep_images_cached; - public: - static void set_keep_images_cached(bool p_enable); - void create(int p_width, int p_height, Image::Format p_format, uint32_t p_flags = FLAGS_DEFAULT); void create_from_image(const Ref<Image> &p_image, uint32_t p_flags = FLAGS_DEFAULT); diff --git a/scene/resources/theme.cpp b/scene/resources/theme.cpp index 8d1a24dbf8..69258bc834 100644 --- a/scene/resources/theme.cpp +++ b/scene/resources/theme.cpp @@ -621,8 +621,8 @@ void Theme::clear() { void Theme::copy_default_theme() { - Ref<Theme> default_theme = get_default(); - copy_theme(default_theme); + Ref<Theme> default_theme2 = get_default(); + copy_theme(default_theme2); } void Theme::copy_theme(const Ref<Theme> &p_other) { diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp index 5a2e7245a2..3c83de91fd 100644 --- a/scene/resources/tile_set.cpp +++ b/scene/resources/tile_set.cpp @@ -614,7 +614,7 @@ Vector2 TileSet::autotile_get_subtile_for_bitmask(int p_id, uint16_t p_bitmask, if (coords.size() == 0) { return autotile_get_icon_coordinate(p_id); } else { - return coords[Math::random(0, (int)coords.size())]; + return coords[Math::rand() % coords.size()]; } } diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp index d96b37938f..692c28ed99 100644 --- a/scene/resources/visual_shader.cpp +++ b/scene/resources/visual_shader.cpp @@ -569,7 +569,7 @@ bool VisualShader::_set(const StringName &p_name, const Variant &p_value) { String mode = name.get_slicec('/', 1); int value = p_value; if (value == 0) { - modes.erase(mode); //means its default anyway, so dont store it + modes.erase(mode); //means it's default anyway, so don't store it } else { modes[mode] = value; } diff --git a/scene/resources/visual_shader_nodes.cpp b/scene/resources/visual_shader_nodes.cpp index a89b70d1ea..d95e0e2da1 100644 --- a/scene/resources/visual_shader_nodes.cpp +++ b/scene/resources/visual_shader_nodes.cpp @@ -324,7 +324,7 @@ String VisualShaderNodeTexture::generate_global(Shader::Mode p_mode, VisualShade String u = "uniform sampler2D " + make_unique_id(p_type, p_id, "tex"); switch (texture_type) { case TYPE_DATA: break; - case TYPE_COLOR: u += " : hint_color"; break; + case TYPE_COLOR: u += " : hint_albedo"; break; case TYPE_NORMALMAP: u += " : hint_normal"; break; } return u + ";"; @@ -554,7 +554,7 @@ String VisualShaderNodeCubeMap::generate_global(Shader::Mode p_mode, VisualShade String u = "uniform sampler2DCube " + make_unique_id(p_type, p_id, "cube"); switch (texture_type) { case TYPE_DATA: break; - case TYPE_COLOR: u += " : hint_color"; break; + case TYPE_COLOR: u += " : hint_albedo"; break; case TYPE_NORMALMAP: u += " : hint_normal"; break; } return u + ";"; diff --git a/scene/scene_string_names.cpp b/scene/scene_string_names.cpp index 305e4fc735..634f4d7160 100644 --- a/scene/scene_string_names.cpp +++ b/scene/scene_string_names.cpp @@ -203,4 +203,6 @@ SceneStringNames::SceneStringNames() { _mesh_changed = StaticCString::create("_mesh_changed"); parameters_base_path = "parameters/"; + + tracks_changed = "tracks_changed"; } diff --git a/scene/scene_string_names.h b/scene/scene_string_names.h index 103b06dbc1..bc75165b8c 100644 --- a/scene/scene_string_names.h +++ b/scene/scene_string_names.h @@ -32,7 +32,7 @@ #define SCENE_STRING_NAMES_H #include "core/node_path.h" -#include "core/string_db.h" +#include "core/string_name.h" class SceneStringNames { friend void register_scene_types(); @@ -205,6 +205,8 @@ public: StringName parameters_base_path; + StringName tracks_changed; + enum { MAX_MATERIALS = 32 }; diff --git a/servers/audio/audio_stream.cpp b/servers/audio/audio_stream.cpp index 51b9d5a4a2..bd98619e92 100644 --- a/servers/audio/audio_stream.cpp +++ b/servers/audio/audio_stream.cpp @@ -83,8 +83,8 @@ void AudioStreamPlaybackResampled::mix(AudioFrame *p_buffer, float p_rate_scale, _mix_internal(internal_buffer + 4, INTERNAL_BUFFER_LEN); } else { //fill with silence, not playing - for (int i = 0; i < INTERNAL_BUFFER_LEN; ++i) { - internal_buffer[i + 4] = AudioFrame(0, 0); + for (int j = 0; j < INTERNAL_BUFFER_LEN; ++j) { + internal_buffer[j + 4] = AudioFrame(0, 0); } } mix_offset -= (INTERNAL_BUFFER_LEN << FP_BITS); diff --git a/servers/audio/reverb_sw.cpp b/servers/audio/reverb_sw.cpp index 8adc21b406..63bf1a7eaa 100644 --- a/servers/audio/reverb_sw.cpp +++ b/servers/audio/reverb_sw.cpp @@ -39,9 +39,6 @@ #define rangeloop(c, min, max) \ for ((c) = (min); (c) < (max); (c)++) -#define ABSDIFF(x, y) \ - (((x) < (y)) ? ((y) - (x)) : ((x) - (y))) - #define MULSHIFT_S32(Factor1, Factor2, Bits) \ ((int)(((int64_t)(Factor1) * (Factor2)) >> (Bits))) diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp index 3b1734287a..a2e5813a4f 100644 --- a/servers/audio_server.cpp +++ b/servers/audio_server.cpp @@ -977,7 +977,7 @@ void AudioServer::update() { uint64_t driver_time = AudioDriver::get_singleton()->get_profiling_time(); uint64_t server_time = prof_time; - // Substract the server time from the driver time + // Subtract the server time from the driver time if (driver_time > server_time) driver_time -= server_time; @@ -995,7 +995,7 @@ void AudioServer::update() { values.push_back(String(bus->name) + bus->effects[j].effect->get_name()); values.push_back(USEC_TO_SEC(bus->effects[j].prof_time)); - // Substract the effect time from the driver and server times + // Subtract the effect time from the driver and server times if (driver_time > bus->effects[j].prof_time) driver_time -= bus->effects[j].prof_time; if (server_time > bus->effects[j].prof_time) diff --git a/servers/physics/body_sw.cpp b/servers/physics/body_sw.cpp index 23f16c246e..f0fbbafe1c 100644 --- a/servers/physics/body_sw.cpp +++ b/servers/physics/body_sw.cpp @@ -652,7 +652,7 @@ void BodySW::simulate_motion(const Transform& p_xform,real_t p_step) { linear_velocity=(p_xform.origin - get_transform().origin)/p_step; //compute a FAKE angular velocity, not so easy - Matrix3 rot=get_transform().basis.orthonormalized().transposed() * p_xform.basis.orthonormalized(); + Basis rot=get_transform().basis.orthonormalized().transposed() * p_xform.basis.orthonormalized(); Vector3 axis; real_t angle; diff --git a/servers/physics/collision_object_sw.h b/servers/physics/collision_object_sw.h index 6e6b66dac2..5c14d5aaf9 100644 --- a/servers/physics/collision_object_sw.h +++ b/servers/physics/collision_object_sw.h @@ -130,7 +130,7 @@ public: _FORCE_INLINE_ const Transform &get_shape_transform(int p_index) const { return shapes[p_index].xform; } _FORCE_INLINE_ const Transform &get_shape_inv_transform(int p_index) const { return shapes[p_index].xform_inv; } _FORCE_INLINE_ const AABB &get_shape_aabb(int p_index) const { return shapes[p_index].aabb_cache; } - _FORCE_INLINE_ const real_t get_shape_area(int p_index) const { return shapes[p_index].area_cache; } + _FORCE_INLINE_ real_t get_shape_area(int p_index) const { return shapes[p_index].area_cache; } _FORCE_INLINE_ Transform get_transform() const { return transform; } _FORCE_INLINE_ Transform get_inv_transform() const { return inv_transform; } diff --git a/servers/physics/collision_solver_sat.cpp b/servers/physics/collision_solver_sat.cpp index fd919343f0..baf7431e28 100644 --- a/servers/physics/collision_solver_sat.cpp +++ b/servers/physics/collision_solver_sat.cpp @@ -821,9 +821,9 @@ static void _collision_box_capsule(const ShapeSW *p_a, const Transform &p_transf // test edges of A - for (int i = 0; i < 3; i++) { + for (int j = 0; j < 3; j++) { - Vector3 axis = point_axis.cross(p_transform_a.basis.get_axis(i)).cross(p_transform_a.basis.get_axis(i)).normalized(); + Vector3 axis = point_axis.cross(p_transform_a.basis.get_axis(j)).cross(p_transform_a.basis.get_axis(j)).normalized(); if (!separator.test_axis(axis)) return; @@ -1337,7 +1337,7 @@ static void _collision_convex_polygon_convex_polygon(const ShapeSW *p_a, const T return; } } - //edge-vertex( hsell) + //edge-vertex (shell) for (int i = 0; i < edge_count_A; i++) { @@ -1438,7 +1438,7 @@ static void _collision_convex_polygon_face(const ShapeSW *p_a, const Transform & return; } } - //edge-vertex( hsell) + //edge-vertex (shell) for (int i = 0; i < edge_count; i++) { diff --git a/servers/physics/joints/cone_twist_joint_sw.cpp b/servers/physics/joints/cone_twist_joint_sw.cpp index 05778ee9b0..268b9eefeb 100644 --- a/servers/physics/joints/cone_twist_joint_sw.cpp +++ b/servers/physics/joints/cone_twist_joint_sw.cpp @@ -205,9 +205,9 @@ bool ConeTwistJointSW::setup(real_t p_timestep) { // Twist limits if (m_twistSpan >= real_t(0.)) { - Vector3 b2Axis2 = B->get_transform().basis.xform(this->m_rbBFrame.basis.get_axis(1)); + Vector3 b2Axis22 = B->get_transform().basis.xform(this->m_rbBFrame.basis.get_axis(1)); Quat rotationArc = Quat(b2Axis1, b1Axis1); - Vector3 TwistRef = rotationArc.xform(b2Axis2); + Vector3 TwistRef = rotationArc.xform(b2Axis22); real_t twist = atan2fast(TwistRef.dot(b1Axis3), TwistRef.dot(b1Axis2)); real_t lockedFreeFactor = (m_twistSpan > real_t(0.05f)) ? m_limitSoftness : real_t(0.); diff --git a/servers/physics/shape_sw.cpp b/servers/physics/shape_sw.cpp index fdc5eccc5a..d40de669fd 100644 --- a/servers/physics/shape_sw.cpp +++ b/servers/physics/shape_sw.cpp @@ -32,7 +32,7 @@ #include "core/math/geometry.h" #include "core/math/quick_hull.h" -#include "core/sort.h" +#include "core/sort_array.h" #define _POINT_SNAP 0.001953125 #define _EDGE_IS_VALID_SUPPORT_THRESHOLD 0.0002 diff --git a/servers/physics/space_sw.cpp b/servers/physics/space_sw.cpp index 1087cd2483..4ab92715f4 100644 --- a/servers/physics/space_sw.cpp +++ b/servers/physics/space_sw.cpp @@ -277,7 +277,7 @@ bool PhysicsDirectSpaceStateSW::cast_motion(const RID &p_shape, const Transform real_t hi = 1; Vector3 mnormal = p_motion.normalized(); - for (int i = 0; i < 8; i++) { //steps should be customizable.. + for (int j = 0; j < 8; j++) { //steps should be customizable.. real_t ofs = (low + hi) * 0.5; @@ -387,6 +387,7 @@ struct _RestCallbackData { Vector3 best_contact; Vector3 best_normal; real_t best_len; + real_t min_allowed_depth; }; static void _rest_cbk_result(const Vector3 &p_point_A, const Vector3 &p_point_B, void *p_userdata) { @@ -395,6 +396,8 @@ static void _rest_cbk_result(const Vector3 &p_point_A, const Vector3 &p_point_B, Vector3 contact_rel = p_point_B - p_point_A; real_t len = contact_rel.length(); + if (len < rd->min_allowed_depth) + return; if (len <= rd->best_len) return; @@ -418,6 +421,7 @@ bool PhysicsDirectSpaceStateSW::rest_info(RID p_shape, const Transform &p_shape_ rcd.best_len = 0; rcd.best_object = NULL; rcd.best_shape = 0; + rcd.min_allowed_depth = space->test_motion_min_contact_depth; for (int i = 0; i < amount; i++) { @@ -593,7 +597,6 @@ int SpaceSW::test_body_ray_separation(BodySW *p_body, const Transform &p_transfo bool collided = false; int amount = _cull_aabb_for_body(p_body, body_aabb); - int ray_index = 0; for (int j = 0; j < p_body->get_shape_count(); j++) { if (p_body->is_shape_set_as_disabled(j)) @@ -627,7 +630,19 @@ int SpaceSW::test_body_ray_separation(BodySW *p_body, const Transform &p_transfo collided = true; } - if (ray_index < p_result_max) { + int ray_index = -1; //reuse shape + for (int k = 0; k < rays_found; k++) { + if (r_results[ray_index].collision_local_shape == j) { + ray_index = k; + } + } + + if (ray_index == -1 && rays_found < p_result_max) { + ray_index = rays_found; + rays_found++; + } + + if (ray_index != -1) { PhysicsServer::SeparationResult &result = r_results[ray_index]; for (int k = 0; k < cbk.amount; k++) { @@ -642,9 +657,10 @@ int SpaceSW::test_body_ray_separation(BodySW *p_body, const Transform &p_transfo result.collision_depth = depth; result.collision_point = b; result.collision_normal = (b - a).normalized(); - result.collision_local_shape = shape_idx; + result.collision_local_shape = j; result.collider = col_obj->get_self(); result.collider_id = col_obj->get_instance_id(); + result.collider_shape = shape_idx; //result.collider_metadata = col_obj->get_shape_metadata(shape_idx); if (col_obj->get_type() == CollisionObjectSW::TYPE_BODY) { BodySW *body = (BodySW *)col_obj; @@ -658,12 +674,8 @@ int SpaceSW::test_body_ray_separation(BodySW *p_body, const Transform &p_transfo } } } - - ray_index++; } - rays_found = MAX(ray_index, rays_found); - if (!collided || recover_motion == Vector3()) { break; } @@ -717,6 +729,11 @@ bool SpaceSW::test_body_motion(BodySW *p_body, const Transform &p_from, const Ve } if (!shapes_found) { + if (r_result) { + *r_result = PhysicsServer::MotionResult(); + r_result->motion = p_motion; + } + return false; } @@ -855,7 +872,7 @@ bool SpaceSW::test_body_motion(BodySW *p_body, const Transform &p_from, const Ve real_t hi = 1; Vector3 mnormal = p_motion.normalized(); - for (int i = 0; i < 8; i++) { //steps should be customizable.. + for (int k = 0; k < 8; k++) { //steps should be customizable.. real_t ofs = (low + hi) * 0.5; @@ -924,6 +941,7 @@ bool SpaceSW::test_body_motion(BodySW *p_body, const Transform &p_from, const Ve rcd.best_len = 0; rcd.best_object = NULL; rcd.best_shape = 0; + rcd.min_allowed_depth = test_motion_min_contact_depth; Transform body_shape_xform = ugt * p_body->get_shape_transform(best_shape); ShapeSW *body_shape = p_body->get_shape(best_shape); @@ -1148,6 +1166,7 @@ void SpaceSW::set_param(PhysicsServer::SpaceParameter p_param, real_t p_value) { case PhysicsServer::SPACE_PARAM_BODY_TIME_TO_SLEEP: body_time_to_sleep = p_value; break; case PhysicsServer::SPACE_PARAM_BODY_ANGULAR_VELOCITY_DAMP_RATIO: body_angular_velocity_damp_ratio = p_value; break; case PhysicsServer::SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS: constraint_bias = p_value; break; + case PhysicsServer::SPACE_PARAM_TEST_MOTION_MIN_CONTACT_DEPTH: test_motion_min_contact_depth = p_value; break; } } @@ -1163,6 +1182,7 @@ real_t SpaceSW::get_param(PhysicsServer::SpaceParameter p_param) const { case PhysicsServer::SPACE_PARAM_BODY_TIME_TO_SLEEP: return body_time_to_sleep; case PhysicsServer::SPACE_PARAM_BODY_ANGULAR_VELOCITY_DAMP_RATIO: return body_angular_velocity_damp_ratio; case PhysicsServer::SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS: return constraint_bias; + case PhysicsServer::SPACE_PARAM_TEST_MOTION_MIN_CONTACT_DEPTH: return test_motion_min_contact_depth; } return 0; } @@ -1198,6 +1218,7 @@ SpaceSW::SpaceSW() { contact_recycle_radius = 0.01; contact_max_separation = 0.05; contact_max_allowed_penetration = 0.01; + test_motion_min_contact_depth = 0.00001; constraint_bias = 0.01; body_linear_velocity_sleep_threshold = GLOBAL_DEF("physics/3d/sleep_threshold_linear", 0.1); diff --git a/servers/physics/space_sw.h b/servers/physics/space_sw.h index ae6f349e51..3aaa552845 100644 --- a/servers/physics/space_sw.h +++ b/servers/physics/space_sw.h @@ -96,6 +96,7 @@ private: real_t contact_max_separation; real_t contact_max_allowed_penetration; real_t constraint_bias; + real_t test_motion_min_contact_depth; enum { diff --git a/servers/physics_2d/body_pair_2d_sw.cpp b/servers/physics_2d/body_pair_2d_sw.cpp index ccdaf0b508..46ea0fd65d 100644 --- a/servers/physics_2d/body_pair_2d_sw.cpp +++ b/servers/physics_2d/body_pair_2d_sw.cpp @@ -303,7 +303,7 @@ bool BodyPair2DSW::setup(real_t p_step) { Contact &c = contacts[i]; if (!c.reused) continue; - if (c.normal.dot(direction) < 0) + if (c.normal.dot(direction) > 0) //greater (normal inverted) continue; valid = true; @@ -326,7 +326,7 @@ bool BodyPair2DSW::setup(real_t p_step) { Contact &c = contacts[i]; if (!c.reused) continue; - if (c.normal.dot(direction) < 0) + if (c.normal.dot(direction) < 0) //less (normal ok) continue; valid = true; diff --git a/servers/physics_2d/shape_2d_sw.cpp b/servers/physics_2d/shape_2d_sw.cpp index 558700f400..56b87f620c 100644 --- a/servers/physics_2d/shape_2d_sw.cpp +++ b/servers/physics_2d/shape_2d_sw.cpp @@ -31,7 +31,7 @@ #include "shape_2d_sw.h" #include "core/math/geometry.h" -#include "core/sort.h" +#include "core/sort_array.h" void Shape2DSW::configure(const Rect2 &p_aabb) { aabb = p_aabb; @@ -369,8 +369,11 @@ void RectangleShape2DSW::get_supports(const Vector2 &p_normal, Vector2 *r_suppor } bool RectangleShape2DSW::contains_point(const Vector2 &p_point) const { - - return Math::abs(p_point.x) < half_extents.x && Math::abs(p_point.y) < half_extents.y; + float x = p_point.x; + float y = p_point.y; + float edge_x = half_extents.x; + float edge_y = half_extents.y; + return (x >= -edge_x) && (x < edge_x) && (y >= -edge_y) && (y < edge_y); } bool RectangleShape2DSW::intersect_segment(const Vector2 &p_begin, const Vector2 &p_end, Vector2 &r_point, Vector2 &r_normal) const { @@ -775,22 +778,22 @@ bool ConcavePolygonShape2DSW::intersect_segment(const Vector2 &p_begin, const Ve while (true) { uint32_t node = stack[level] & NODE_IDX_MASK; - const BVH &b = bvhptr[node]; + const BVH &bvh = bvhptr[node]; bool done = false; switch (stack[level] >> VISITED_BIT_SHIFT) { case TEST_AABB_BIT: { - bool valid = b.aabb.intersects_segment(p_begin, p_end); + bool valid = bvh.aabb.intersects_segment(p_begin, p_end); if (!valid) { stack[level] = (VISIT_DONE_BIT << VISITED_BIT_SHIFT) | node; } else { - if (b.left < 0) { + if (bvh.left < 0) { - const Segment &s = segmentptr[b.right]; + const Segment &s = segmentptr[bvh.right]; Vector2 a = pointptr[s.points[0]]; Vector2 b = pointptr[s.points[1]]; @@ -820,14 +823,14 @@ bool ConcavePolygonShape2DSW::intersect_segment(const Vector2 &p_begin, const Ve case VISIT_LEFT_BIT: { stack[level] = (VISIT_RIGHT_BIT << VISITED_BIT_SHIFT) | node; - stack[level + 1] = b.left | TEST_AABB_BIT; + stack[level + 1] = bvh.left | TEST_AABB_BIT; level++; } continue; case VISIT_RIGHT_BIT: { stack[level] = (VISIT_DONE_BIT << VISITED_BIT_SHIFT) | node; - stack[level + 1] = b.right | TEST_AABB_BIT; + stack[level + 1] = bvh.right | TEST_AABB_BIT; level++; } continue; @@ -1025,21 +1028,21 @@ void ConcavePolygonShape2DSW::cull(const Rect2 &p_local_aabb, Callback p_callbac while (true) { uint32_t node = stack[level] & NODE_IDX_MASK; - const BVH &b = bvhptr[node]; + const BVH &bvh = bvhptr[node]; switch (stack[level] >> VISITED_BIT_SHIFT) { case TEST_AABB_BIT: { - bool valid = p_local_aabb.intersects(b.aabb); + bool valid = p_local_aabb.intersects(bvh.aabb); if (!valid) { stack[level] = (VISIT_DONE_BIT << VISITED_BIT_SHIFT) | node; } else { - if (b.left < 0) { + if (bvh.left < 0) { - const Segment &s = segmentptr[b.right]; + const Segment &s = segmentptr[bvh.right]; Vector2 a = pointptr[s.points[0]]; Vector2 b = pointptr[s.points[1]]; @@ -1058,14 +1061,14 @@ void ConcavePolygonShape2DSW::cull(const Rect2 &p_local_aabb, Callback p_callbac case VISIT_LEFT_BIT: { stack[level] = (VISIT_RIGHT_BIT << VISITED_BIT_SHIFT) | node; - stack[level + 1] = b.left | TEST_AABB_BIT; + stack[level + 1] = bvh.left | TEST_AABB_BIT; level++; } continue; case VISIT_RIGHT_BIT: { stack[level] = (VISIT_DONE_BIT << VISITED_BIT_SHIFT) | node; - stack[level + 1] = b.right | TEST_AABB_BIT; + stack[level + 1] = bvh.right | TEST_AABB_BIT; level++; } continue; diff --git a/servers/physics_2d/space_2d_sw.cpp b/servers/physics_2d/space_2d_sw.cpp index 5ed70803ed..831764b40c 100644 --- a/servers/physics_2d/space_2d_sw.cpp +++ b/servers/physics_2d/space_2d_sw.cpp @@ -280,7 +280,7 @@ bool Physics2DDirectSpaceStateSW::cast_motion(const RID &p_shape, const Transfor real_t hi = 1; Vector2 mnormal = p_motion.normalized(); - for (int i = 0; i < 8; i++) { //steps should be customizable.. + for (int j = 0; j < 8; j++) { //steps should be customizable.. real_t ofs = (low + hi) * 0.5; @@ -375,6 +375,7 @@ struct _RestCallbackData2D { real_t best_len; Vector2 valid_dir; real_t valid_depth; + real_t min_allowed_depth; }; static void _rest_cbk_result(const Vector2 &p_point_A, const Vector2 &p_point_B, void *p_userdata) { @@ -390,6 +391,10 @@ static void _rest_cbk_result(const Vector2 &p_point_A, const Vector2 &p_point_B, Vector2 contact_rel = p_point_B - p_point_A; real_t len = contact_rel.length(); + + if (len < rd->min_allowed_depth) + return; + if (len <= rd->best_len) return; @@ -416,6 +421,7 @@ bool Physics2DDirectSpaceStateSW::rest_info(RID p_shape, const Transform2D &p_sh rcd.best_len = 0; rcd.best_object = NULL; rcd.best_shape = 0; + rcd.min_allowed_depth = space->test_motion_min_contact_depth; for (int i = 0; i < amount; i++) { @@ -512,6 +518,9 @@ int Space2DSW::test_body_ray_separation(Body2DSW *p_body, const Transform2D &p_t if (p_body->is_shape_set_as_disabled(i)) continue; + if (p_body->get_shape(i)->get_type() != Physics2DServer::SHAPE_RAY) + continue; + if (!shapes_found) { body_aabb = p_body->get_shape_aabb(i); shapes_found = true; @@ -555,7 +564,6 @@ int Space2DSW::test_body_ray_separation(Body2DSW *p_body, const Transform2D &p_t bool collided = false; int amount = _cull_aabb_for_body(p_body, body_aabb); - int ray_index = 0; for (int j = 0; j < p_body->get_shape_count(); j++) { if (p_body->is_shape_set_as_disabled(j)) @@ -587,6 +595,10 @@ int Space2DSW::test_body_ray_separation(Body2DSW *p_body, const Transform2D &p_t Transform2D col_obj_shape_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx); + /* + * There is no point in supporting one way collisions with ray shapes, as they will always collide in the desired + * direction. Use a short ray shape if you want to achieve a similar effect. + * if (col_obj->is_shape_set_as_one_way_collision(shape_idx)) { cbk.valid_dir = col_obj_shape_xform.get_axis(1).normalized(); @@ -594,10 +606,15 @@ int Space2DSW::test_body_ray_separation(Body2DSW *p_body, const Transform2D &p_t cbk.invalid_by_dir = 0; } else { - cbk.valid_dir = Vector2(); - cbk.valid_depth = 0; - cbk.invalid_by_dir = 0; +*/ + + cbk.valid_dir = Vector2(); + cbk.valid_depth = 0; + cbk.invalid_by_dir = 0; + + /* } + */ Shape2DSW *against_shape = col_obj->get_shape(shape_idx); if (CollisionSolver2DSW::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj_shape_xform, Vector2(), cbkres, cbkptr, NULL, p_margin)) { @@ -605,7 +622,20 @@ int Space2DSW::test_body_ray_separation(Body2DSW *p_body, const Transform2D &p_t collided = true; } - if (ray_index < p_result_max) { + int ray_index = -1; //reuse shape + for (int k = 0; k < rays_found; k++) { + if (r_results[ray_index].collision_local_shape == j) { + ray_index = k; + } + } + + if (ray_index == -1 && rays_found < p_result_max) { + ray_index = rays_found; + rays_found++; + } + + if (ray_index != -1) { + Physics2DServer::SeparationResult &result = r_results[ray_index]; for (int k = 0; k < cbk.amount; k++) { @@ -620,7 +650,8 @@ int Space2DSW::test_body_ray_separation(Body2DSW *p_body, const Transform2D &p_t result.collision_depth = depth; result.collision_point = b; result.collision_normal = (b - a).normalized(); - result.collision_local_shape = shape_idx; + result.collision_local_shape = j; + result.collider_shape = shape_idx; result.collider = col_obj->get_self(); result.collider_id = col_obj->get_instance_id(); result.collider_metadata = col_obj->get_shape_metadata(shape_idx); @@ -635,12 +666,8 @@ int Space2DSW::test_body_ray_separation(Body2DSW *p_body, const Transform2D &p_t } } } - - ray_index++; } - rays_found = MAX(ray_index, rays_found); - if (!collided || recover_motion == Vector2()) { break; } @@ -686,6 +713,9 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co if (p_body->is_shape_set_as_disabled(i)) continue; + if (p_exclude_raycast_shapes && p_body->get_shape(i)->get_type() == Physics2DServer::SHAPE_RAY) + continue; + if (!shapes_found) { body_aabb = p_body->get_shape_aabb(i); shapes_found = true; @@ -695,6 +725,10 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co } if (!shapes_found) { + if (r_result) { + *r_result = Physics2DServer::MotionResult(); + r_result->motion = p_motion; + } return false; } @@ -990,15 +1024,24 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co rcd.best_len = 0; rcd.best_object = NULL; rcd.best_shape = 0; + rcd.min_allowed_depth = test_motion_min_contact_depth; //optimization int from_shape = best_shape != -1 ? best_shape : 0; int to_shape = best_shape != -1 ? best_shape + 1 : p_body->get_shape_count(); for (int j = from_shape; j < to_shape; j++) { + + if (p_body->is_shape_set_as_disabled(j)) + continue; + Transform2D body_shape_xform = ugt * p_body->get_shape_transform(j); Shape2DSW *body_shape = p_body->get_shape(j); + if (p_exclude_raycast_shapes && body_shape->get_type() == Physics2DServer::SHAPE_RAY) { + continue; + } + body_aabb.position += p_motion * unsafe; int amount = _cull_aabb_for_body(p_body, body_aabb); @@ -1249,6 +1292,7 @@ void Space2DSW::set_param(Physics2DServer::SpaceParameter p_param, real_t p_valu case Physics2DServer::SPACE_PARAM_BODY_ANGULAR_VELOCITY_SLEEP_THRESHOLD: body_angular_velocity_sleep_threshold = p_value; break; case Physics2DServer::SPACE_PARAM_BODY_TIME_TO_SLEEP: body_time_to_sleep = p_value; break; case Physics2DServer::SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS: constraint_bias = p_value; break; + case Physics2DServer::SPACE_PARAM_TEST_MOTION_MIN_CONTACT_DEPTH: test_motion_min_contact_depth = p_value; break; } } @@ -1263,6 +1307,7 @@ real_t Space2DSW::get_param(Physics2DServer::SpaceParameter p_param) const { case Physics2DServer::SPACE_PARAM_BODY_ANGULAR_VELOCITY_SLEEP_THRESHOLD: return body_angular_velocity_sleep_threshold; case Physics2DServer::SPACE_PARAM_BODY_TIME_TO_SLEEP: return body_time_to_sleep; case Physics2DServer::SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS: return constraint_bias; + case Physics2DServer::SPACE_PARAM_TEST_MOTION_MIN_CONTACT_DEPTH: return test_motion_min_contact_depth; } return 0; } @@ -1299,6 +1344,7 @@ Space2DSW::Space2DSW() { contact_recycle_radius = 1.0; contact_max_separation = 1.5; contact_max_allowed_penetration = 0.3; + test_motion_min_contact_depth = 0.005; constraint_bias = 0.2; body_linear_velocity_sleep_threshold = GLOBAL_DEF("physics/2d/sleep_threshold_linear", 2.0); diff --git a/servers/physics_2d/space_2d_sw.h b/servers/physics_2d/space_2d_sw.h index 64f8c9e156..14c24959b7 100644 --- a/servers/physics_2d/space_2d_sw.h +++ b/servers/physics_2d/space_2d_sw.h @@ -104,6 +104,7 @@ private: real_t contact_max_separation; real_t contact_max_allowed_penetration; real_t constraint_bias; + real_t test_motion_min_contact_depth; enum { diff --git a/servers/physics_2d_server.cpp b/servers/physics_2d_server.cpp index ca914b67e0..3a05791f17 100644 --- a/servers/physics_2d_server.cpp +++ b/servers/physics_2d_server.cpp @@ -693,6 +693,7 @@ void Physics2DServer::_bind_methods() { BIND_ENUM_CONSTANT(SPACE_PARAM_BODY_ANGULAR_VELOCITY_SLEEP_THRESHOLD); BIND_ENUM_CONSTANT(SPACE_PARAM_BODY_TIME_TO_SLEEP); BIND_ENUM_CONSTANT(SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS); + BIND_ENUM_CONSTANT(SPACE_PARAM_TEST_MOTION_MIN_CONTACT_DEPTH); BIND_ENUM_CONSTANT(SHAPE_LINE); BIND_ENUM_CONSTANT(SHAPE_RAY); diff --git a/servers/physics_2d_server.h b/servers/physics_2d_server.h index df7fe46f76..1de9c7df93 100644 --- a/servers/physics_2d_server.h +++ b/servers/physics_2d_server.h @@ -289,6 +289,7 @@ public: SPACE_PARAM_BODY_ANGULAR_VELOCITY_SLEEP_THRESHOLD, SPACE_PARAM_BODY_TIME_TO_SLEEP, SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS, + SPACE_PARAM_TEST_MOTION_MIN_CONTACT_DEPTH, }; virtual void space_set_param(RID p_space, SpaceParameter p_param, real_t p_value) = 0; @@ -504,6 +505,12 @@ public: RID collider; int collider_shape; Variant collider_metadata; + + MotionResult() { + collision_local_shape = 0; + collider_shape = 0; + collider_id = 0; + } }; virtual bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, float p_margin = 0.001, MotionResult *r_result = NULL, bool p_exclude_raycast_shapes = true) = 0; diff --git a/servers/physics_server.cpp b/servers/physics_server.cpp index 967e74d322..0629af663e 100644 --- a/servers/physics_server.cpp +++ b/servers/physics_server.cpp @@ -709,6 +709,8 @@ void PhysicsServer::_bind_methods() { BIND_ENUM_CONSTANT(SPACE_PARAM_BODY_TIME_TO_SLEEP); BIND_ENUM_CONSTANT(SPACE_PARAM_BODY_ANGULAR_VELOCITY_DAMP_RATIO); BIND_ENUM_CONSTANT(SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS); + BIND_ENUM_CONSTANT(SPACE_PARAM_TEST_MOTION_MIN_CONTACT_DEPTH); + BIND_ENUM_CONSTANT(BODY_AXIS_LINEAR_X); BIND_ENUM_CONSTANT(BODY_AXIS_LINEAR_Y); BIND_ENUM_CONSTANT(BODY_AXIS_LINEAR_Z); @@ -737,11 +739,11 @@ const String PhysicsServerManager::setting_property_name("physics/3d/physics_eng void PhysicsServerManager::on_servers_changed() { - String physics_servers("DEFAULT"); + String physics_servers2("DEFAULT"); for (int i = get_servers_count() - 1; 0 <= i; --i) { - physics_servers += "," + get_server_name(i); + physics_servers2 += "," + get_server_name(i); } - ProjectSettings::get_singleton()->set_custom_property_info(setting_property_name, PropertyInfo(Variant::STRING, setting_property_name, PROPERTY_HINT_ENUM, physics_servers)); + ProjectSettings::get_singleton()->set_custom_property_info(setting_property_name, PropertyInfo(Variant::STRING, setting_property_name, PROPERTY_HINT_ENUM, physics_servers2)); } void PhysicsServerManager::register_server(const String &p_name, CreatePhysicsServerCallback p_creat_callback) { diff --git a/servers/physics_server.h b/servers/physics_server.h index 4ba096a994..c71bb01943 100644 --- a/servers/physics_server.h +++ b/servers/physics_server.h @@ -274,6 +274,7 @@ public: SPACE_PARAM_BODY_TIME_TO_SLEEP, SPACE_PARAM_BODY_ANGULAR_VELOCITY_DAMP_RATIO, SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS, + SPACE_PARAM_TEST_MOTION_MIN_CONTACT_DEPTH }; virtual void space_set_param(RID p_space, SpaceParameter p_param, real_t p_value) = 0; @@ -492,6 +493,11 @@ public: RID collider; int collider_shape; Variant collider_metadata; + MotionResult() { + collision_local_shape = 0; + collider_id = 0; + collider_shape = 0; + } }; virtual bool body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, MotionResult *r_result = NULL, bool p_exclude_raycast_shapes = true) = 0; diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h index 33081dcd0c..8502ef5bf7 100644 --- a/servers/visual/rasterizer.h +++ b/servers/visual/rasterizer.h @@ -870,7 +870,7 @@ public: Rect2 global_rect_cache; const Rect2 &get_rect() const { - if (custom_rect || !rect_dirty) + if (custom_rect || (!rect_dirty && !update_when_visible)) return rect; //must update rect @@ -940,9 +940,8 @@ public: const Item::CommandPrimitive *primitive = static_cast<const Item::CommandPrimitive *>(c); r.position = primitive->points[0]; - for (int i = 1; i < primitive->points.size(); i++) { - - r.expand_to(primitive->points[i]); + for (int j = 1; j < primitive->points.size(); j++) { + r.expand_to(primitive->points[j]); } } break; case Item::Command::TYPE_POLYGON: { @@ -951,9 +950,8 @@ public: int l = polygon->points.size(); const Point2 *pp = &polygon->points[0]; r.position = pp[0]; - for (int i = 1; i < l; i++) { - - r.expand_to(pp[i]); + for (int j = 1; j < l; j++) { + r.expand_to(pp[j]); } } break; case Item::Command::TYPE_MESH: { diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp index c2dae7c2d5..639946916d 100644 --- a/servers/visual/shader_language.cpp +++ b/servers/visual/shader_language.cpp @@ -2184,11 +2184,11 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, OperatorNode *p bool fail = false; - for (int i = 0; i < args.size(); i++) { + for (int j = 0; j < args.size(); j++) { - if (get_scalar_type(args[i]) == args[i] && p_func->arguments[i + 1]->type == Node::TYPE_CONSTANT && convert_constant(static_cast<ConstantNode *>(p_func->arguments[i + 1]), pfunc->arguments[i].type)) { + if (get_scalar_type(args[j]) == args[j] && p_func->arguments[j + 1]->type == Node::TYPE_CONSTANT && convert_constant(static_cast<ConstantNode *>(p_func->arguments[j + 1]), pfunc->arguments[j].type)) { //all good - } else if (args[i] != pfunc->arguments[i].type) { + } else if (args[j] != pfunc->arguments[j].type) { fail = true; break; } @@ -2897,7 +2897,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons /* OK now see what's NEXT to the operator.. */ while (true) { - TkPos pos = _get_tkpos(); + TkPos pos2 = _get_tkpos(); tk = _get_token(); if (tk.type == TK_CURSOR) { @@ -3181,7 +3181,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons expr = op; } else { - _set_tkpos(pos); + _set_tkpos(pos2); break; } } @@ -3374,10 +3374,10 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons if (!_validate_operator(op, &op->return_cache)) { String at; - for (int i = 0; i < op->arguments.size(); i++) { - if (i > 0) + for (int j = 0; j < op->arguments.size(); j++) { + if (j > 0) at += " and "; - at += get_datatype_name(op->arguments[i]->get_datatype()); + at += get_datatype_name(op->arguments[j]->get_datatype()); } _set_error("Invalid arguments to unary operator '" + get_operator_text(op->op) + "' :" + at); return NULL; @@ -4103,17 +4103,17 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct if (uniform) { - ShaderNode::Uniform uniform; + ShaderNode::Uniform uniform2; if (is_sampler_type(type)) { - uniform.texture_order = texture_uniforms++; - uniform.order = -1; + uniform2.texture_order = texture_uniforms++; + uniform2.order = -1; } else { - uniform.texture_order = -1; - uniform.order = uniforms++; + uniform2.texture_order = -1; + uniform2.order = uniforms++; } - uniform.type = type; - uniform.precission = precision; + uniform2.type = type; + uniform2.precision = precision; //todo parse default value @@ -4124,26 +4124,26 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct tk = _get_token(); if (tk.type == TK_HINT_WHITE_TEXTURE) { - uniform.hint = ShaderNode::Uniform::HINT_WHITE; + uniform2.hint = ShaderNode::Uniform::HINT_WHITE; } else if (tk.type == TK_HINT_BLACK_TEXTURE) { - uniform.hint = ShaderNode::Uniform::HINT_BLACK; + uniform2.hint = ShaderNode::Uniform::HINT_BLACK; } else if (tk.type == TK_HINT_NORMAL_TEXTURE) { - uniform.hint = ShaderNode::Uniform::HINT_NORMAL; + uniform2.hint = ShaderNode::Uniform::HINT_NORMAL; } else if (tk.type == TK_HINT_ANISO_TEXTURE) { - uniform.hint = ShaderNode::Uniform::HINT_ANISO; + uniform2.hint = ShaderNode::Uniform::HINT_ANISO; } else if (tk.type == TK_HINT_ALBEDO_TEXTURE) { - uniform.hint = ShaderNode::Uniform::HINT_ALBEDO; + uniform2.hint = ShaderNode::Uniform::HINT_ALBEDO; } else if (tk.type == TK_HINT_BLACK_ALBEDO_TEXTURE) { - uniform.hint = ShaderNode::Uniform::HINT_BLACK_ALBEDO; + uniform2.hint = ShaderNode::Uniform::HINT_BLACK_ALBEDO; } else if (tk.type == TK_HINT_COLOR) { if (type != TYPE_VEC4) { _set_error("Color hint is for vec4 only"); return ERR_PARSE_ERROR; } - uniform.hint = ShaderNode::Uniform::HINT_COLOR; + uniform2.hint = ShaderNode::Uniform::HINT_COLOR; } else if (tk.type == TK_HINT_RANGE) { - uniform.hint = ShaderNode::Uniform::HINT_RANGE; + uniform2.hint = ShaderNode::Uniform::HINT_RANGE; if (type != TYPE_FLOAT && type != TYPE_INT) { _set_error("Range hint is for float and int only"); return ERR_PARSE_ERROR; @@ -4169,8 +4169,8 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct return ERR_PARSE_ERROR; } - uniform.hint_range[0] = tk.constant; - uniform.hint_range[0] *= sign; + uniform2.hint_range[0] = tk.constant; + uniform2.hint_range[0] *= sign; tk = _get_token(); @@ -4193,8 +4193,8 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct return ERR_PARSE_ERROR; } - uniform.hint_range[1] = tk.constant; - uniform.hint_range[1] *= sign; + uniform2.hint_range[1] = tk.constant; + uniform2.hint_range[1] *= sign; tk = _get_token(); @@ -4206,13 +4206,13 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct return ERR_PARSE_ERROR; } - uniform.hint_range[2] = tk.constant; + uniform2.hint_range[2] = tk.constant; tk = _get_token(); } else { if (type == TYPE_INT) { - uniform.hint_range[2] = 1; + uniform2.hint_range[2] = 1; } else { - uniform.hint_range[2] = 0.001; + uniform2.hint_range[2] = 0.001; } } @@ -4225,7 +4225,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct _set_error("Expected valid type hint after ':'."); } - if (uniform.hint != ShaderNode::Uniform::HINT_RANGE && uniform.hint != ShaderNode::Uniform::HINT_NONE && uniform.hint != ShaderNode::Uniform::HINT_COLOR && type <= TYPE_MAT4) { + if (uniform2.hint != ShaderNode::Uniform::HINT_RANGE && uniform2.hint != ShaderNode::Uniform::HINT_NONE && uniform2.hint != ShaderNode::Uniform::HINT_COLOR && type <= TYPE_MAT4) { _set_error("This hint is only for sampler types"); return ERR_PARSE_ERROR; } @@ -4245,16 +4245,16 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct ConstantNode *cn = static_cast<ConstantNode *>(expr); - uniform.default_value.resize(cn->values.size()); + uniform2.default_value.resize(cn->values.size()); - if (!convert_constant(cn, uniform.type, uniform.default_value.ptrw())) { - _set_error("Can't convert constant to " + get_datatype_name(uniform.type)); + if (!convert_constant(cn, uniform2.type, uniform2.default_value.ptrw())) { + _set_error("Can't convert constant to " + get_datatype_name(uniform2.type)); return ERR_PARSE_ERROR; } tk = _get_token(); } - shader->uniforms[name] = uniform; + shader->uniforms[name] = uniform2; if (tk.type != TK_SEMICOLON) { _set_error("Expected ';'"); @@ -4264,7 +4264,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct ShaderNode::Varying varying; varying.type = type; - varying.precission = precision; + varying.precision = precision; varying.interpolation = interpolation; shader->varyings[name] = varying; diff --git a/servers/visual/shader_language.h b/servers/visual/shader_language.h index b908f9539b..67c273d267 100644 --- a/servers/visual/shader_language.h +++ b/servers/visual/shader_language.h @@ -33,7 +33,7 @@ #include "core/list.h" #include "core/map.h" -#include "core/string_db.h" +#include "core/string_name.h" #include "core/typedefs.h" #include "core/ustring.h" #include "core/variant.h" @@ -42,7 +42,6 @@ class ShaderLanguage { public: enum TokenType { - TK_EMPTY, TK_IDENTIFIER, TK_TRUE, @@ -267,18 +266,15 @@ public: FLOW_OP_SWITCH, FLOW_OP_CONTINUE, FLOW_OP_DISCARD - }; enum ArgumentQualifier { ARGUMENT_QUALIFIER_IN, ARGUMENT_QUALIFIER_OUT, ARGUMENT_QUALIFIER_INOUT, - }; struct Node { - Node *next; enum Type { @@ -296,7 +292,9 @@ public: Type type; virtual DataType get_datatype() const { return TYPE_VOID; } - + Node(Type t) : + next(NULL), + type(t) {} virtual ~Node() {} }; @@ -311,18 +309,17 @@ public: Node *nodes; struct OperatorNode : public Node { - DataType return_cache; DataPrecision return_precision_cache; Operator op; Vector<Node *> arguments; virtual DataType get_datatype() const { return return_cache; } - OperatorNode() { - type = TYPE_OPERATOR; - return_cache = TYPE_VOID; - return_precision_cache = PRECISION_DEFAULT; - } + OperatorNode() : + Node(TYPE_OPERATOR), + return_cache(TYPE_VOID), + return_precision_cache(PRECISION_DEFAULT), + op(OP_EQUAL) {} }; struct VariableNode : public Node { @@ -330,20 +327,16 @@ public: StringName name; virtual DataType get_datatype() const { return datatype_cache; } - VariableNode() { - - type = TYPE_VARIABLE; - datatype_cache = TYPE_VOID; - } + VariableNode() : + Node(TYPE_VARIABLE), + datatype_cache(TYPE_VOID) {} }; struct VariableDeclarationNode : public Node { - DataPrecision precision; DataType datatype; struct Declaration { - StringName name; Node *initializer; }; @@ -351,13 +344,13 @@ public: Vector<Declaration> declarations; virtual DataType get_datatype() const { return datatype; } - VariableDeclarationNode() { - type = TYPE_VARIABLE_DECLARATION; - } + VariableDeclarationNode() : + Node(TYPE_VARIABLE_DECLARATION), + precision(PRECISION_DEFAULT), + datatype(TYPE_VOID) {} }; struct ConstantNode : public Node { - DataType datatype; union Value { @@ -370,7 +363,9 @@ public: Vector<Value> values; virtual DataType get_datatype() const { return datatype; } - ConstantNode() { type = TYPE_CONSTANT; } + ConstantNode() : + Node(TYPE_CONSTANT), + datatype(TYPE_VOID) {} }; struct FunctionNode; @@ -388,39 +383,41 @@ public: Map<StringName, Variable> variables; List<Node *> statements; bool single_statement; - BlockNode() { - type = TYPE_BLOCK; - parent_block = NULL; - parent_function = NULL; - single_statement = false; - } + + BlockNode() : + Node(TYPE_BLOCK), + parent_function(NULL), + parent_block(NULL), + single_statement(false) {} }; struct ControlFlowNode : public Node { - FlowOperation flow_op; Vector<Node *> expressions; Vector<BlockNode *> blocks; - ControlFlowNode() { - type = TYPE_CONTROL_FLOW; - flow_op = FLOW_OP_IF; - } + + ControlFlowNode() : + Node(TYPE_CONTROL_FLOW), + flow_op(FLOW_OP_IF) {} }; struct MemberNode : public Node { - DataType basetype; DataType datatype; StringName name; Node *owner; + virtual DataType get_datatype() const { return datatype; } - MemberNode() { type = TYPE_MEMBER; } + + MemberNode() : + Node(TYPE_MEMBER), + basetype(TYPE_VOID), + datatype(TYPE_VOID), + owner(NULL) {} }; struct FunctionNode : public Node { - struct Argument { - ArgumentQualifier qualifier; StringName name; DataType type; @@ -434,16 +431,15 @@ public: BlockNode *body; bool can_discard; - FunctionNode() { - type = TYPE_FUNCTION; - return_type = TYPE_VOID; - return_precision = PRECISION_DEFAULT; - can_discard = false; - } + FunctionNode() : + Node(TYPE_FUNCTION), + return_type(TYPE_VOID), + return_precision(PRECISION_DEFAULT), + body(NULL), + can_discard(false) {} }; struct ShaderNode : public Node { - struct Function { StringName name; FunctionNode *function; @@ -454,7 +450,12 @@ public: struct Varying { DataType type; DataInterpolation interpolation; - DataPrecision precission; + DataPrecision precision; + + Varying() : + type(TYPE_VOID), + interpolation(INTERPOLATION_FLAT), + precision(PRECISION_DEFAULT) {} }; struct Uniform { @@ -474,16 +475,20 @@ public: int order; int texture_order; DataType type; - DataPrecision precission; + DataPrecision precision; Vector<ConstantNode::Value> default_value; Hint hint; float hint_range[3]; - Uniform() { - hint = HINT_NONE; - hint_range[0] = 0; - hint_range[1] = 1; - hint_range[2] = 0.001; + Uniform() : + order(0), + texture_order(0), + type(TYPE_VOID), + precision(PRECISION_DEFAULT), + hint(HINT_NONE) { + hint_range[0] = 0.0f; + hint_range[1] = 1.0f; + hint_range[2] = 0.001f; } }; @@ -493,11 +498,11 @@ public: Vector<Function> functions; - ShaderNode() { type = TYPE_SHADER; } + ShaderNode() : + Node(TYPE_SHADER) {} }; struct Expression { - bool is_op; union { Operator op; @@ -506,7 +511,6 @@ public: }; struct VarInfo { - StringName name; DataType type; }; @@ -522,7 +526,6 @@ public: }; struct Token { - TokenType type; StringName text; double constant; @@ -556,11 +559,14 @@ public: struct BuiltInInfo { DataType type; bool constant; - BuiltInInfo() {} - BuiltInInfo(DataType p_type, bool p_constant = false) { - type = p_type; - constant = p_constant; - } + + BuiltInInfo() : + type(TYPE_VOID), + constant(false) {} + + BuiltInInfo(DataType p_type, bool p_constant = false) : + type(p_type), + constant(p_constant) {} }; struct FunctionInfo { @@ -573,6 +579,7 @@ private: TokenType token; const char *text; }; + static const KeyWord keyword_list[]; bool error_set; @@ -628,22 +635,18 @@ private: }; bool _find_identifier(const BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, const StringName &p_identifier, DataType *r_data_type = NULL, IdentifierType *r_type = NULL); - bool _is_operator_assign(Operator p_op) const; bool _validate_assign(Node *p_node, const Map<StringName, BuiltInInfo> &p_builtin_types, String *r_message = NULL); - bool _validate_operator(OperatorNode *p_op, DataType *r_ret_type = NULL); struct BuiltinFuncDef { - enum { MAX_ARGS = 5 }; const char *name; DataType rettype; const DataType args[MAX_ARGS]; }; - struct BuiltinFuncOutArgs { //arguments used as out in built in funcions - + struct BuiltinFuncOutArgs { //arguments used as out in built in functions const char *name; int argument; }; @@ -656,20 +659,17 @@ private: int completion_argument; bool _get_completable_identifier(BlockNode *p_block, CompletionType p_type, StringName &identifier); - static const BuiltinFuncDef builtin_func_defs[]; static const BuiltinFuncOutArgs builtin_func_out_args[]; - bool _validate_function_call(BlockNode *p_block, OperatorNode *p_func, DataType *r_ret_type); + bool _validate_function_call(BlockNode *p_block, OperatorNode *p_func, DataType *r_ret_type); bool _parse_function_arguments(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, OperatorNode *p_func, int *r_complete_arg = NULL); Node *_parse_expression(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types); - ShaderLanguage::Node *_reduce_expression(BlockNode *p_block, ShaderLanguage::Node *p_node); - Node *_parse_and_reduce_expression(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types); + Node *_parse_and_reduce_expression(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types); Error _parse_block(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, bool p_just_one = false, bool p_can_break = false, bool p_can_continue = false); - Error _parse_shader(const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const Set<String> &p_shader_types); public: diff --git a/servers/visual/visual_server_canvas.cpp b/servers/visual/visual_server_canvas.cpp index bb02027479..fb57de5a7b 100644 --- a/servers/visual/visual_server_canvas.cpp +++ b/servers/visual/visual_server_canvas.cpp @@ -29,7 +29,7 @@ /*************************************************************************/ #include "visual_server_canvas.h" -#include "visual_server_global.h" +#include "visual_server_globals.h" #include "visual_server_raster.h" #include "visual_server_viewport.h" @@ -267,24 +267,24 @@ void VisualServerCanvas::render_canvas(Canvas *p_canvas, const Transform2D &p_tr for (int i = 0; i < l; i++) { - const Canvas::ChildItem &ci = p_canvas->child_items[i]; - _render_canvas_item_tree(ci.item, p_transform, p_clip_rect, p_canvas->modulate, p_lights); + const Canvas::ChildItem &ci2 = p_canvas->child_items[i]; + _render_canvas_item_tree(ci2.item, p_transform, p_clip_rect, p_canvas->modulate, p_lights); //mirroring (useful for scrolling backgrounds) - if (ci.mirror.x != 0) { + if (ci2.mirror.x != 0) { - Transform2D xform2 = p_transform * Transform2D(0, Vector2(ci.mirror.x, 0)); - _render_canvas_item_tree(ci.item, xform2, p_clip_rect, p_canvas->modulate, p_lights); + Transform2D xform2 = p_transform * Transform2D(0, Vector2(ci2.mirror.x, 0)); + _render_canvas_item_tree(ci2.item, xform2, p_clip_rect, p_canvas->modulate, p_lights); } - if (ci.mirror.y != 0) { + if (ci2.mirror.y != 0) { - Transform2D xform2 = p_transform * Transform2D(0, Vector2(0, ci.mirror.y)); - _render_canvas_item_tree(ci.item, xform2, p_clip_rect, p_canvas->modulate, p_lights); + Transform2D xform2 = p_transform * Transform2D(0, Vector2(0, ci2.mirror.y)); + _render_canvas_item_tree(ci2.item, xform2, p_clip_rect, p_canvas->modulate, p_lights); } - if (ci.mirror.y != 0 && ci.mirror.x != 0) { + if (ci2.mirror.y != 0 && ci2.mirror.x != 0) { - Transform2D xform2 = p_transform * Transform2D(0, ci.mirror); - _render_canvas_item_tree(ci.item, xform2, p_clip_rect, p_canvas->modulate, p_lights); + Transform2D xform2 = p_transform * Transform2D(0, ci2.mirror); + _render_canvas_item_tree(ci2.item, xform2, p_clip_rect, p_canvas->modulate, p_lights); } } } diff --git a/servers/visual/visual_server_global.cpp b/servers/visual/visual_server_globals.cpp index 2d6d489759..5c247c7f0f 100644 --- a/servers/visual/visual_server_global.cpp +++ b/servers/visual/visual_server_globals.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* visual_server_global.cpp */ +/* visual_server_globals.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,7 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "visual_server_global.h" +#include "visual_server_globals.h" RasterizerStorage *VisualServerGlobals::storage = NULL; RasterizerCanvas *VisualServerGlobals::canvas_render = NULL; diff --git a/servers/visual/visual_server_global.h b/servers/visual/visual_server_globals.h index b510307e81..04d52aa1eb 100644 --- a/servers/visual/visual_server_global.h +++ b/servers/visual/visual_server_globals.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* visual_server_global.h */ +/* visual_server_globals.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef VISUALSERVERGLOBAL_H -#define VISUALSERVERGLOBAL_H +#ifndef VISUAL_SERVER_GLOBALS_H +#define VISUAL_SERVER_GLOBALS_H #include "rasterizer.h" @@ -51,4 +51,4 @@ public: #define VSG VisualServerGlobals -#endif // VISUALSERVERGLOBAL_H +#endif // VISUAL_SERVER_GLOBALS_H diff --git a/servers/visual/visual_server_raster.cpp b/servers/visual/visual_server_raster.cpp index 7be3bc562d..6622433b17 100644 --- a/servers/visual/visual_server_raster.cpp +++ b/servers/visual/visual_server_raster.cpp @@ -33,9 +33,9 @@ #include "core/io/marshalls.h" #include "core/os/os.h" #include "core/project_settings.h" -#include "core/sort.h" +#include "core/sort_array.h" #include "visual_server_canvas.h" -#include "visual_server_global.h" +#include "visual_server_globals.h" #include "visual_server_scene.h" // careful, these may run in different threads than the visual server diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h index e6434189f9..89a759b963 100644 --- a/servers/visual/visual_server_raster.h +++ b/servers/visual/visual_server_raster.h @@ -31,12 +31,11 @@ #ifndef VISUAL_SERVER_RASTER_H #define VISUAL_SERVER_RASTER_H -#include "core/allocators.h" #include "core/math/octree.h" #include "servers/visual/rasterizer.h" #include "servers/visual_server.h" #include "visual_server_canvas.h" -#include "visual_server_global.h" +#include "visual_server_globals.h" #include "visual_server_scene.h" #include "visual_server_viewport.h" /** diff --git a/servers/visual/visual_server_scene.cpp b/servers/visual/visual_server_scene.cpp index c8d64fca45..01d00ccc21 100644 --- a/servers/visual/visual_server_scene.cpp +++ b/servers/visual/visual_server_scene.cpp @@ -30,7 +30,7 @@ #include "visual_server_scene.h" #include "core/os/os.h" -#include "visual_server_global.h" +#include "visual_server_globals.h" #include "visual_server_raster.h" #include <new> /* CAMERA API */ @@ -2480,7 +2480,7 @@ void VisualServerScene::_setup_gi_probe(Instance *p_instance) { uint32_t a = uint32_t(alpha_block[x][y]) - min_alpha; //convert range to 3 bits a = int((a * 7.0 / (max_alpha - min_alpha)) + 0.5); - a = CLAMP(a, 0, 7); //just to be sure + a = MAX(a, 7); //just to be sure a = 7 - a; //because range is inverted in this mode if (a == 0) { //do none, remain @@ -2916,7 +2916,7 @@ void VisualServerScene::_bake_gi_probe(Instance *p_gi_probe) { uint32_t idx = level_cells[j]; - uint32_t r = (uint32_t(local_data[idx].energy[0]) / probe_data->dynamic.bake_dynamic_range) >> 2; + uint32_t r2 = (uint32_t(local_data[idx].energy[0]) / probe_data->dynamic.bake_dynamic_range) >> 2; uint32_t g = (uint32_t(local_data[idx].energy[1]) / probe_data->dynamic.bake_dynamic_range) >> 2; uint32_t b = (uint32_t(local_data[idx].energy[2]) / probe_data->dynamic.bake_dynamic_range) >> 2; uint32_t a = (cells[idx].level_alpha >> 8) & 0xFF; @@ -2924,10 +2924,10 @@ void VisualServerScene::_bake_gi_probe(Instance *p_gi_probe) { uint32_t mm_ofs = sizes[0] * sizes[1] * (local_data[idx].pos[2]) + sizes[0] * (local_data[idx].pos[1]) + (local_data[idx].pos[0]); mm_ofs *= 4; //for RGBA (4 bytes) - mipmapw[mm_ofs + 0] = uint8_t(CLAMP(r, 0, 255)); - mipmapw[mm_ofs + 1] = uint8_t(CLAMP(g, 0, 255)); - mipmapw[mm_ofs + 2] = uint8_t(CLAMP(b, 0, 255)); - mipmapw[mm_ofs + 3] = uint8_t(CLAMP(a, 0, 255)); + mipmapw[mm_ofs + 0] = uint8_t(MAX(r2, 255)); + mipmapw[mm_ofs + 1] = uint8_t(MAX(g, 255)); + mipmapw[mm_ofs + 2] = uint8_t(MAX(b, 255)); + mipmapw[mm_ofs + 3] = uint8_t(MAX(a, 255)); } } } else if (probe_data->dynamic.compression == RasterizerStorage::GI_PROBE_S3TC) { diff --git a/servers/visual/visual_server_scene.h b/servers/visual/visual_server_scene.h index 539855bdc4..7583acd88f 100644 --- a/servers/visual/visual_server_scene.h +++ b/servers/visual/visual_server_scene.h @@ -33,7 +33,6 @@ #include "servers/visual/rasterizer.h" -#include "core/allocators.h" #include "core/math/geometry.h" #include "core/math/octree.h" #include "core/os/semaphore.h" @@ -120,7 +119,6 @@ public: VS::ScenarioDebugMode debug; RID self; - // well wtf, balloon allocator is slower? Octree<Instance, true> octree; diff --git a/servers/visual/visual_server_viewport.cpp b/servers/visual/visual_server_viewport.cpp index 7a7ae3a823..d6e43b0f00 100644 --- a/servers/visual/visual_server_viewport.cpp +++ b/servers/visual/visual_server_viewport.cpp @@ -32,7 +32,7 @@ #include "core/project_settings.h" #include "visual_server_canvas.h" -#include "visual_server_global.h" +#include "visual_server_globals.h" #include "visual_server_scene.h" void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::Eyes p_eye) { diff --git a/servers/visual_server.cpp b/servers/visual_server.cpp index 14c9a29ae5..c61e2b99e2 100644 --- a/servers/visual_server.cpp +++ b/servers/visual_server.cpp @@ -1163,11 +1163,11 @@ void VisualServer::mesh_add_surface_from_arrays(RID p_mesh, PrimitiveType p_prim PoolVector<uint8_t> noindex; AABB laabb; - Error err = _surface_set_data(p_blend_shapes[i], format & ~ARRAY_FORMAT_INDEX, offsets, total_elem_size, vertex_array_shape, array_len, noindex, 0, laabb, bone_aabb); + Error err2 = _surface_set_data(p_blend_shapes[i], format & ~ARRAY_FORMAT_INDEX, offsets, total_elem_size, vertex_array_shape, array_len, noindex, 0, laabb, bone_aabb); aabb.merge_with(laabb); - if (err) { + if (err2) { ERR_EXPLAIN("Invalid blend shape array format for surface"); - ERR_FAIL_COND(err != OK); + ERR_FAIL_COND(err2 != OK); } blend_shape_data.push_back(vertex_array_shape); diff --git a/thirdparty/README.md b/thirdparty/README.md index 738835c70a..c70e931c52 100644 --- a/thirdparty/README.md +++ b/thirdparty/README.md @@ -280,15 +280,14 @@ Godot build configurations, check them out when updating. ## mbedtls - Upstream: https://tls.mbed.org/ -- Version: 2.12.0 +- Version: 2.16.0 - License: Apache 2.0 -File extracted from upstream release tarball `mbedtls-2.12.0-apache.tgz`: +File extracted from upstream release tarball `mbedtls-2.16.0-apache.tgz`: - All `*.h` from `include/mbedtls/` to `thirdparty/mbedtls/include/mbedtls/` - All `*.c` from `library/` to `thirdparty/mbedtls/library/` - Applied the patch in `thirdparty/mbedtls/1453.diff` (PR 1453). Soon to be merged upstream. Check it out at next update. - ## miniupnpc - Upstream: https://github.com/miniupnp/miniupnp/tree/master/miniupnpc @@ -471,17 +470,6 @@ Files extracted from upstream source: - License.txt -## rtaudio - -- Upstream: http://www.music.mcgill.ca/~gary/rtaudio/ -- Version: 4.1.2 -- License: MIT-like - -Files extracted from upstream source: - -- `RtAudio.{cpp,h}` - - ## squish - Upstream: https://sourceforge.net/projects/libsquish diff --git a/thirdparty/mbedtls/1453.diff b/thirdparty/mbedtls/1453.diff index 6630ad861f..b1c9c43ed2 100644 --- a/thirdparty/mbedtls/1453.diff +++ b/thirdparty/mbedtls/1453.diff @@ -1,8 +1,8 @@ diff --git a/library/entropy_poll.c b/library/entropy_poll.c -index 67900c46c8..cefe882d2a 100644 +index 4556f88a5..ba56b70f7 100644 --- a/library/entropy_poll.c +++ b/library/entropy_poll.c -@@ -54,28 +54,43 @@ +@@ -61,28 +61,43 @@ #define _WIN32_WINNT 0x0400 #endif #include <windows.h> @@ -54,7 +54,7 @@ index 67900c46c8..cefe882d2a 100644 return( 0 ); diff --git a/library/x509_crt.c b/library/x509_crt.c -index 290c1eb3d1..3cf1743821 100644 +index 76558342e..35a134950 100644 --- a/library/x509_crt.c +++ b/library/x509_crt.c @@ -65,6 +65,19 @@ @@ -77,20 +77,20 @@ index 290c1eb3d1..3cf1743821 100644 #else #include <time.h> #endif -@@ -1126,6 +1139,7 @@ int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path ) +@@ -1278,6 +1291,7 @@ int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path ) char filename[MAX_PATH]; char *p; size_t len = strlen( path ); -+ int length_as_int = 0; ++ int lengthAsInt = 0; WIN32_FIND_DATAW file_data; HANDLE hFind; -@@ -1140,7 +1154,18 @@ int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path ) +@@ -1292,7 +1306,18 @@ int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path ) p = filename + len; filename[len++] = '*'; - w_ret = MultiByteToWideChar( CP_ACP, 0, filename, (int)len, szDir, -+ if ( FAILED ( SizeTToInt( len, &length_as_int ) ) ) ++ if ( FAILED ( SizeTToInt( len, &lengthAsInt ) ) ) + return( MBEDTLS_ERR_X509_FILE_IO_ERROR ); + + /* @@ -101,20 +101,20 @@ index 290c1eb3d1..3cf1743821 100644 + * incoming string are less than MAX_PATH to avoid a buffer overrun with + * MultiByteToWideChar(). + */ -+ w_ret = MultiByteToWideChar( CP_ACP, 0, filename, length_as_int, szDir, ++ w_ret = MultiByteToWideChar( CP_ACP, 0, filename, lengthAsInt, szDir, MAX_PATH - 3 ); if( w_ret == 0 ) return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); -@@ -1157,8 +1182,11 @@ int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path ) +@@ -1309,8 +1334,11 @@ int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path ) if( file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) continue; -+ if ( FAILED( SizeTToInt( wcslen( file_data.cFileName ), &length_as_int ) ) ) ++ if ( FAILED( SizeTToInt( wcslen( file_data.cFileName ), &lengthAsInt ) ) ) + return( MBEDTLS_ERR_X509_FILE_IO_ERROR ); + w_ret = WideCharToMultiByte( CP_ACP, 0, file_data.cFileName, - lstrlenW( file_data.cFileName ), -+ length_as_int, ++ lengthAsInt, p, (int) len - 1, NULL, NULL ); if( w_ret == 0 ) diff --git a/thirdparty/mbedtls/include/mbedtls/aes.h b/thirdparty/mbedtls/include/mbedtls/aes.h index f6603d5962..b42e564efc 100644 --- a/thirdparty/mbedtls/include/mbedtls/aes.h +++ b/thirdparty/mbedtls/include/mbedtls/aes.h @@ -60,7 +60,11 @@ /* Error codes in range 0x0021-0x0025 */ #define MBEDTLS_ERR_AES_BAD_INPUT_DATA -0x0021 /**< Invalid input data. */ + +/* MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE is deprecated and should not be used. */ #define MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE -0x0023 /**< Feature not available. For example, an unsupported AES key size. */ + +/* MBEDTLS_ERR_AES_HW_ACCEL_FAILED is deprecated and should not be used. */ #define MBEDTLS_ERR_AES_HW_ACCEL_FAILED -0x0025 /**< AES hardware accelerator failed. */ #if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ @@ -79,7 +83,7 @@ extern "C" { /** * \brief The AES context-type definition. */ -typedef struct +typedef struct mbedtls_aes_context { int nr; /*!< The number of rounds. */ uint32_t *rk; /*!< AES round keys. */ @@ -98,7 +102,7 @@ mbedtls_aes_context; /** * \brief The AES XTS context-type definition. */ -typedef struct +typedef struct mbedtls_aes_xts_context { mbedtls_aes_context crypt; /*!< The AES context to use for AES block encryption or decryption. */ @@ -117,7 +121,7 @@ typedef struct * It must be the first API called before using * the context. * - * \param ctx The AES context to initialize. + * \param ctx The AES context to initialize. This must not be \c NULL. */ void mbedtls_aes_init( mbedtls_aes_context *ctx ); @@ -125,6 +129,8 @@ void mbedtls_aes_init( mbedtls_aes_context *ctx ); * \brief This function releases and clears the specified AES context. * * \param ctx The AES context to clear. + * If this is \c NULL, this function does nothing. + * Otherwise, the context must have been at least initialized. */ void mbedtls_aes_free( mbedtls_aes_context *ctx ); @@ -135,7 +141,7 @@ void mbedtls_aes_free( mbedtls_aes_context *ctx ); * It must be the first API called before using * the context. * - * \param ctx The AES XTS context to initialize. + * \param ctx The AES XTS context to initialize. This must not be \c NULL. */ void mbedtls_aes_xts_init( mbedtls_aes_xts_context *ctx ); @@ -143,6 +149,8 @@ void mbedtls_aes_xts_init( mbedtls_aes_xts_context *ctx ); * \brief This function releases and clears the specified AES XTS context. * * \param ctx The AES XTS context to clear. + * If this is \c NULL, this function does nothing. + * Otherwise, the context must have been at least initialized. */ void mbedtls_aes_xts_free( mbedtls_aes_xts_context *ctx ); #endif /* MBEDTLS_CIPHER_MODE_XTS */ @@ -151,7 +159,9 @@ void mbedtls_aes_xts_free( mbedtls_aes_xts_context *ctx ); * \brief This function sets the encryption key. * * \param ctx The AES context to which the key should be bound. + * It must be initialized. * \param key The encryption key. + * This must be a readable buffer of size \p keybits bits. * \param keybits The size of data passed in bits. Valid options are: * <ul><li>128 bits</li> * <li>192 bits</li> @@ -167,7 +177,9 @@ int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key, * \brief This function sets the decryption key. * * \param ctx The AES context to which the key should be bound. + * It must be initialized. * \param key The decryption key. + * This must be a readable buffer of size \p keybits bits. * \param keybits The size of data passed. Valid options are: * <ul><li>128 bits</li> * <li>192 bits</li> @@ -185,8 +197,10 @@ int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key, * sets the encryption key. * * \param ctx The AES XTS context to which the key should be bound. + * It must be initialized. * \param key The encryption key. This is comprised of the XTS key1 * concatenated with the XTS key2. + * This must be a readable buffer of size \p keybits bits. * \param keybits The size of \p key passed in bits. Valid options are: * <ul><li>256 bits (each of key1 and key2 is a 128-bit key)</li> * <li>512 bits (each of key1 and key2 is a 256-bit key)</li></ul> @@ -203,8 +217,10 @@ int mbedtls_aes_xts_setkey_enc( mbedtls_aes_xts_context *ctx, * sets the decryption key. * * \param ctx The AES XTS context to which the key should be bound. + * It must be initialized. * \param key The decryption key. This is comprised of the XTS key1 * concatenated with the XTS key2. + * This must be a readable buffer of size \p keybits bits. * \param keybits The size of \p key passed in bits. Valid options are: * <ul><li>256 bits (each of key1 and key2 is a 128-bit key)</li> * <li>512 bits (each of key1 and key2 is a 256-bit key)</li></ul> @@ -230,10 +246,13 @@ int mbedtls_aes_xts_setkey_dec( mbedtls_aes_xts_context *ctx, * call to this API with the same context. * * \param ctx The AES context to use for encryption or decryption. + * It must be initialized and bound to a key. * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or * #MBEDTLS_AES_DECRYPT. - * \param input The 16-Byte buffer holding the input data. - * \param output The 16-Byte buffer holding the output data. + * \param input The buffer holding the input data. + * It must be readable and at least \c 16 Bytes long. + * \param output The buffer where the output data will be written. + * It must be writeable and at least \c 16 Bytes long. * \return \c 0 on success. */ @@ -256,8 +275,8 @@ int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx, * mbedtls_aes_setkey_enc() or mbedtls_aes_setkey_dec() must be called * before the first call to this API with the same context. * - * \note This function operates on aligned blocks, that is, the input size - * must be a multiple of the AES block size of 16 Bytes. + * \note This function operates on full blocks, that is, the input size + * must be a multiple of the AES block size of \c 16 Bytes. * * \note Upon exit, the content of the IV is updated so that you can * call the same function again on the next @@ -268,13 +287,17 @@ int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx, * * * \param ctx The AES context to use for encryption or decryption. + * It must be initialized and bound to a key. * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or * #MBEDTLS_AES_DECRYPT. * \param length The length of the input data in Bytes. This must be a - * multiple of the block size (16 Bytes). + * multiple of the block size (\c 16 Bytes). * \param iv Initialization vector (updated after use). + * It must be a readable and writeable buffer of \c 16 Bytes. * \param input The buffer holding the input data. + * It must be readable and of size \p length Bytes. * \param output The buffer holding the output data. + * It must be writeable and of size \p length Bytes. * * \return \c 0 on success. * \return #MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH @@ -302,9 +325,10 @@ int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx, * returns #MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH. * * \param ctx The AES XTS context to use for AES XTS operations. + * It must be initialized and bound to a key. * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or * #MBEDTLS_AES_DECRYPT. - * \param length The length of a data unit in bytes. This can be any + * \param length The length of a data unit in Bytes. This can be any * length between 16 bytes and 2^24 bytes inclusive * (between 1 and 2^20 block cipher blocks). * \param data_unit The address of the data unit encoded as an array of 16 @@ -312,15 +336,15 @@ int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx, * is typically the index of the block device sector that * contains the data. * \param input The buffer holding the input data (which is an entire - * data unit). This function reads \p length bytes from \p + * data unit). This function reads \p length Bytes from \p * input. * \param output The buffer holding the output data (which is an entire - * data unit). This function writes \p length bytes to \p + * data unit). This function writes \p length Bytes to \p * output. * * \return \c 0 on success. * \return #MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH if \p length is - * smaller than an AES block in size (16 bytes) or if \p + * smaller than an AES block in size (16 Bytes) or if \p * length is larger than 2^20 blocks (16 MiB). */ int mbedtls_aes_crypt_xts( mbedtls_aes_xts_context *ctx, @@ -356,13 +380,18 @@ int mbedtls_aes_crypt_xts( mbedtls_aes_xts_context *ctx, * * * \param ctx The AES context to use for encryption or decryption. + * It must be initialized and bound to a key. * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or * #MBEDTLS_AES_DECRYPT. - * \param length The length of the input data. + * \param length The length of the input data in Bytes. * \param iv_off The offset in IV (updated after use). + * It must point to a valid \c size_t. * \param iv The initialization vector (updated after use). + * It must be a readable and writeable buffer of \c 16 Bytes. * \param input The buffer holding the input data. + * It must be readable and of size \p length Bytes. * \param output The buffer holding the output data. + * It must be writeable and of size \p length Bytes. * * \return \c 0 on success. */ @@ -397,12 +426,16 @@ int mbedtls_aes_crypt_cfb128( mbedtls_aes_context *ctx, * * * \param ctx The AES context to use for encryption or decryption. + * It must be initialized and bound to a key. * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or * #MBEDTLS_AES_DECRYPT * \param length The length of the input data. * \param iv The initialization vector (updated after use). + * It must be a readable and writeable buffer of \c 16 Bytes. * \param input The buffer holding the input data. + * It must be readable and of size \p length Bytes. * \param output The buffer holding the output data. + * It must be writeable and of size \p length Bytes. * * \return \c 0 on success. */ @@ -447,11 +480,16 @@ int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx, * will compromise security. * * \param ctx The AES context to use for encryption or decryption. + * It must be initialized and bound to a key. * \param length The length of the input data. * \param iv_off The offset in IV (updated after use). + * It must point to a valid \c size_t. * \param iv The initialization vector (updated after use). + * It must be a readable and writeable buffer of \c 16 Bytes. * \param input The buffer holding the input data. + * It must be readable and of size \p length Bytes. * \param output The buffer holding the output data. + * It must be writeable and of size \p length Bytes. * * \return \c 0 on success. */ @@ -523,15 +561,21 @@ int mbedtls_aes_crypt_ofb( mbedtls_aes_context *ctx, * securely discarded as soon as it's no longer needed. * * \param ctx The AES context to use for encryption or decryption. + * It must be initialized and bound to a key. * \param length The length of the input data. * \param nc_off The offset in the current \p stream_block, for * resuming within the current cipher stream. The * offset pointer should be 0 at the start of a stream. + * It must point to a valid \c size_t. * \param nonce_counter The 128-bit nonce and counter. + * It must be a readable-writeable buffer of \c 16 Bytes. * \param stream_block The saved stream block for resuming. This is * overwritten by the function. + * It must be a readable-writeable buffer of \c 16 Bytes. * \param input The buffer holding the input data. + * It must be readable and of size \p length Bytes. * \param output The buffer holding the output data. + * It must be writeable and of size \p length Bytes. * * \return \c 0 on success. */ @@ -584,7 +628,7 @@ int mbedtls_internal_aes_decrypt( mbedtls_aes_context *ctx, * \brief Deprecated internal AES block encryption function * without return value. * - * \deprecated Superseded by mbedtls_aes_encrypt_ext() in 2.5.0. + * \deprecated Superseded by mbedtls_internal_aes_encrypt() * * \param ctx The AES context to use for encryption. * \param input Plaintext block. @@ -598,7 +642,7 @@ MBEDTLS_DEPRECATED void mbedtls_aes_encrypt( mbedtls_aes_context *ctx, * \brief Deprecated internal AES block decryption function * without return value. * - * \deprecated Superseded by mbedtls_aes_decrypt_ext() in 2.5.0. + * \deprecated Superseded by mbedtls_internal_aes_decrypt() * * \param ctx The AES context to use for decryption. * \param input Ciphertext block. diff --git a/thirdparty/mbedtls/include/mbedtls/aesni.h b/thirdparty/mbedtls/include/mbedtls/aesni.h index 746baa0e17..0196f49b87 100644 --- a/thirdparty/mbedtls/include/mbedtls/aesni.h +++ b/thirdparty/mbedtls/include/mbedtls/aesni.h @@ -2,6 +2,9 @@ * \file aesni.h * * \brief AES-NI for hardware AES acceleration on some Intel processors + * + * \warning These functions are only for internal use by other library + * functions; you must not call them directly. */ /* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved @@ -42,7 +45,10 @@ extern "C" { #endif /** - * \brief AES-NI features detection routine + * \brief Internal function to detect the AES-NI feature in CPUs. + * + * \note This function is only for internal use by other library + * functions; you must not call it directly. * * \param what The feature to detect * (MBEDTLS_AESNI_AES or MBEDTLS_AESNI_CLMUL) @@ -52,7 +58,10 @@ extern "C" { int mbedtls_aesni_has_support( unsigned int what ); /** - * \brief AES-NI AES-ECB block en(de)cryption + * \brief Internal AES-NI AES-ECB block encryption and decryption + * + * \note This function is only for internal use by other library + * functions; you must not call it directly. * * \param ctx AES context * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT @@ -62,12 +71,15 @@ int mbedtls_aesni_has_support( unsigned int what ); * \return 0 on success (cannot fail) */ int mbedtls_aesni_crypt_ecb( mbedtls_aes_context *ctx, - int mode, - const unsigned char input[16], - unsigned char output[16] ); + int mode, + const unsigned char input[16], + unsigned char output[16] ); /** - * \brief GCM multiplication: c = a * b in GF(2^128) + * \brief Internal GCM multiplication: c = a * b in GF(2^128) + * + * \note This function is only for internal use by other library + * functions; you must not call it directly. * * \param c Result * \param a First operand @@ -77,21 +89,29 @@ int mbedtls_aesni_crypt_ecb( mbedtls_aes_context *ctx, * elements of GF(2^128) as per the GCM spec. */ void mbedtls_aesni_gcm_mult( unsigned char c[16], - const unsigned char a[16], - const unsigned char b[16] ); + const unsigned char a[16], + const unsigned char b[16] ); /** - * \brief Compute decryption round keys from encryption round keys + * \brief Internal round key inversion. This function computes + * decryption round keys from the encryption round keys. + * + * \note This function is only for internal use by other library + * functions; you must not call it directly. * * \param invkey Round keys for the equivalent inverse cipher * \param fwdkey Original round keys (for encryption) * \param nr Number of rounds (that is, number of round keys minus one) */ void mbedtls_aesni_inverse_key( unsigned char *invkey, - const unsigned char *fwdkey, int nr ); + const unsigned char *fwdkey, + int nr ); /** - * \brief Perform key expansion (for encryption) + * \brief Internal key expansion for encryption + * + * \note This function is only for internal use by other library + * functions; you must not call it directly. * * \param rk Destination buffer where the round keys are written * \param key Encryption key @@ -100,8 +120,8 @@ void mbedtls_aesni_inverse_key( unsigned char *invkey, * \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_KEY_LENGTH */ int mbedtls_aesni_setkey_enc( unsigned char *rk, - const unsigned char *key, - size_t bits ); + const unsigned char *key, + size_t bits ); #ifdef __cplusplus } diff --git a/thirdparty/mbedtls/include/mbedtls/arc4.h b/thirdparty/mbedtls/include/mbedtls/arc4.h index f11fc5be0a..c43f4065f1 100644 --- a/thirdparty/mbedtls/include/mbedtls/arc4.h +++ b/thirdparty/mbedtls/include/mbedtls/arc4.h @@ -36,6 +36,7 @@ #include <stddef.h> +/* MBEDTLS_ERR_ARC4_HW_ACCEL_FAILED is deprecated and should not be used. */ #define MBEDTLS_ERR_ARC4_HW_ACCEL_FAILED -0x0019 /**< ARC4 hardware accelerator failed. */ #ifdef __cplusplus @@ -53,7 +54,7 @@ extern "C" { * security risk. We recommend considering stronger ciphers instead. * */ -typedef struct +typedef struct mbedtls_arc4_context { int x; /*!< permutation index */ int y; /*!< permutation index */ diff --git a/thirdparty/mbedtls/include/mbedtls/aria.h b/thirdparty/mbedtls/include/mbedtls/aria.h index bae0621b23..1e8956ed13 100644 --- a/thirdparty/mbedtls/include/mbedtls/aria.h +++ b/thirdparty/mbedtls/include/mbedtls/aria.h @@ -39,6 +39,8 @@ #include <stddef.h> #include <stdint.h> +#include "platform_util.h" + #define MBEDTLS_ARIA_ENCRYPT 1 /**< ARIA encryption. */ #define MBEDTLS_ARIA_DECRYPT 0 /**< ARIA decryption. */ @@ -46,9 +48,18 @@ #define MBEDTLS_ARIA_MAX_ROUNDS 16 /**< Maxiumum number of rounds in ARIA. */ #define MBEDTLS_ARIA_MAX_KEYSIZE 32 /**< Maximum size of an ARIA key in bytes. */ -#define MBEDTLS_ERR_ARIA_INVALID_KEY_LENGTH -0x005C /**< Invalid key length. */ -#define MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH -0x005E /**< Invalid data input length. */ +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#define MBEDTLS_ERR_ARIA_INVALID_KEY_LENGTH MBEDTLS_DEPRECATED_NUMERIC_CONSTANT( -0x005C ) +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ +#define MBEDTLS_ERR_ARIA_BAD_INPUT_DATA -0x005C /**< Bad input data. */ + +#define MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH -0x005E /**< Invalid data input length. */ + +/* MBEDTLS_ERR_ARIA_FEATURE_UNAVAILABLE is deprecated and should not be used. + */ #define MBEDTLS_ERR_ARIA_FEATURE_UNAVAILABLE -0x005A /**< Feature not available. For example, an unsupported ARIA key size. */ + +/* MBEDTLS_ERR_ARIA_HW_ACCEL_FAILED is deprecated and should not be used. */ #define MBEDTLS_ERR_ARIA_HW_ACCEL_FAILED -0x0058 /**< ARIA hardware accelerator failed. */ #if !defined(MBEDTLS_ARIA_ALT) @@ -62,7 +73,7 @@ extern "C" { /** * \brief The ARIA context-type definition. */ -typedef struct +typedef struct mbedtls_aria_context { unsigned char nr; /*!< The number of rounds (12, 14 or 16) */ /*! The ARIA round keys. */ @@ -80,14 +91,16 @@ mbedtls_aria_context; * It must be the first API called before using * the context. * - * \param ctx The ARIA context to initialize. + * \param ctx The ARIA context to initialize. This must not be \c NULL. */ void mbedtls_aria_init( mbedtls_aria_context *ctx ); /** * \brief This function releases and clears the specified ARIA context. * - * \param ctx The ARIA context to clear. + * \param ctx The ARIA context to clear. This may be \c NULL, in which + * case this function returns immediately. If it is not \c NULL, + * it must point to an initialized ARIA context. */ void mbedtls_aria_free( mbedtls_aria_context *ctx ); @@ -95,14 +108,16 @@ void mbedtls_aria_free( mbedtls_aria_context *ctx ); * \brief This function sets the encryption key. * * \param ctx The ARIA context to which the key should be bound. - * \param key The encryption key. - * \param keybits The size of data passed in bits. Valid options are: + * This must be initialized. + * \param key The encryption key. This must be a readable buffer + * of size \p keybits Bits. + * \param keybits The size of \p key in Bits. Valid options are: * <ul><li>128 bits</li> * <li>192 bits</li> * <li>256 bits</li></ul> * - * \return \c 0 on success or #MBEDTLS_ERR_ARIA_INVALID_KEY_LENGTH - * on failure. + * \return \c 0 on success. + * \return A negative error code on failure. */ int mbedtls_aria_setkey_enc( mbedtls_aria_context *ctx, const unsigned char *key, @@ -112,13 +127,16 @@ int mbedtls_aria_setkey_enc( mbedtls_aria_context *ctx, * \brief This function sets the decryption key. * * \param ctx The ARIA context to which the key should be bound. - * \param key The decryption key. + * This must be initialized. + * \param key The decryption key. This must be a readable buffer + * of size \p keybits Bits. * \param keybits The size of data passed. Valid options are: * <ul><li>128 bits</li> * <li>192 bits</li> * <li>256 bits</li></ul> * - * \return \c 0 on success, or #MBEDTLS_ERR_ARIA_INVALID_KEY_LENGTH on failure. + * \return \c 0 on success. + * \return A negative error code on failure. */ int mbedtls_aria_setkey_dec( mbedtls_aria_context *ctx, const unsigned char *key, @@ -137,10 +155,12 @@ int mbedtls_aria_setkey_dec( mbedtls_aria_context *ctx, * call to this API with the same context. * * \param ctx The ARIA context to use for encryption or decryption. + * This must be initialized and bound to a key. * \param input The 16-Byte buffer holding the input data. * \param output The 16-Byte buffer holding the output data. * \return \c 0 on success. + * \return A negative error code on failure. */ int mbedtls_aria_crypt_ecb( mbedtls_aria_context *ctx, const unsigned char input[MBEDTLS_ARIA_BLOCKSIZE], @@ -172,16 +192,21 @@ int mbedtls_aria_crypt_ecb( mbedtls_aria_context *ctx, * * * \param ctx The ARIA context to use for encryption or decryption. - * \param mode The ARIA operation: #MBEDTLS_ARIA_ENCRYPT or - * #MBEDTLS_ARIA_DECRYPT. + * This must be initialized and bound to a key. + * \param mode The mode of operation. This must be either + * #MBEDTLS_ARIA_ENCRYPT for encryption, or + * #MBEDTLS_ARIA_DECRYPT for decryption. * \param length The length of the input data in Bytes. This must be a * multiple of the block size (16 Bytes). * \param iv Initialization vector (updated after use). - * \param input The buffer holding the input data. - * \param output The buffer holding the output data. + * This must be a readable buffer of size 16 Bytes. + * \param input The buffer holding the input data. This must + * be a readable buffer of length \p length Bytes. + * \param output The buffer holding the output data. This must + * be a writable buffer of length \p length Bytes. * - * \return \c 0 on success, or #MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH - * on failure. + * \return \c 0 on success. + * \return A negative error code on failure. */ int mbedtls_aria_crypt_cbc( mbedtls_aria_context *ctx, int mode, @@ -216,15 +241,22 @@ int mbedtls_aria_crypt_cbc( mbedtls_aria_context *ctx, * * * \param ctx The ARIA context to use for encryption or decryption. - * \param mode The ARIA operation: #MBEDTLS_ARIA_ENCRYPT or - * #MBEDTLS_ARIA_DECRYPT. - * \param length The length of the input data. + * This must be initialized and bound to a key. + * \param mode The mode of operation. This must be either + * #MBEDTLS_ARIA_ENCRYPT for encryption, or + * #MBEDTLS_ARIA_DECRYPT for decryption. + * \param length The length of the input data \p input in Bytes. * \param iv_off The offset in IV (updated after use). + * This must not be larger than 15. * \param iv The initialization vector (updated after use). - * \param input The buffer holding the input data. - * \param output The buffer holding the output data. + * This must be a readable buffer of size 16 Bytes. + * \param input The buffer holding the input data. This must + * be a readable buffer of length \p length Bytes. + * \param output The buffer holding the output data. This must + * be a writable buffer of length \p length Bytes. * * \return \c 0 on success. + * \return A negative error code on failure. */ int mbedtls_aria_crypt_cfb128( mbedtls_aria_context *ctx, int mode, @@ -294,17 +326,24 @@ int mbedtls_aria_crypt_cfb128( mbedtls_aria_context *ctx, * securely discarded as soon as it's no longer needed. * * \param ctx The ARIA context to use for encryption or decryption. - * \param length The length of the input data. - * \param nc_off The offset in the current \p stream_block, for - * resuming within the current cipher stream. The - * offset pointer should be 0 at the start of a stream. - * \param nonce_counter The 128-bit nonce and counter. - * \param stream_block The saved stream block for resuming. This is - * overwritten by the function. - * \param input The buffer holding the input data. - * \param output The buffer holding the output data. - * - * \return \c 0 on success. + * This must be initialized and bound to a key. + * \param length The length of the input data \p input in Bytes. + * \param nc_off The offset in Bytes in the current \p stream_block, + * for resuming within the current cipher stream. The + * offset pointer should be \c 0 at the start of a + * stream. This must not be larger than \c 15 Bytes. + * \param nonce_counter The 128-bit nonce and counter. This must point to + * a read/write buffer of length \c 16 bytes. + * \param stream_block The saved stream block for resuming. This must + * point to a read/write buffer of length \c 16 bytes. + * This is overwritten by the function. + * \param input The buffer holding the input data. This must + * be a readable buffer of length \p length Bytes. + * \param output The buffer holding the output data. This must + * be a writable buffer of length \p length Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. */ int mbedtls_aria_crypt_ctr( mbedtls_aria_context *ctx, size_t length, diff --git a/thirdparty/mbedtls/include/mbedtls/asn1write.h b/thirdparty/mbedtls/include/mbedtls/asn1write.h index f76fc807d0..76c1780b59 100644 --- a/thirdparty/mbedtls/include/mbedtls/asn1write.h +++ b/thirdparty/mbedtls/include/mbedtls/asn1write.h @@ -26,191 +26,272 @@ #include "asn1.h" -#define MBEDTLS_ASN1_CHK_ADD(g, f) do { if( ( ret = f ) < 0 ) return( ret ); else \ - g += ret; } while( 0 ) +#define MBEDTLS_ASN1_CHK_ADD(g, f) \ + do { \ + if( ( ret = f ) < 0 ) \ + return( ret ); \ + else \ + g += ret; \ + } while( 0 ) #ifdef __cplusplus extern "C" { #endif /** - * \brief Write a length field in ASN.1 format - * Note: function works backwards in data buffer + * \brief Write a length field in ASN.1 format. * - * \param p reference to current position pointer - * \param start start of the buffer (for bounds-checking) - * \param len the length to write + * \note This function works backwards in data buffer. * - * \return the length written or a negative error code + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param len The length value to write. + * + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. */ -int mbedtls_asn1_write_len( unsigned char **p, unsigned char *start, size_t len ); - +int mbedtls_asn1_write_len( unsigned char **p, unsigned char *start, + size_t len ); /** - * \brief Write a ASN.1 tag in ASN.1 format - * Note: function works backwards in data buffer + * \brief Write an ASN.1 tag in ASN.1 format. + * + * \note This function works backwards in data buffer. * - * \param p reference to current position pointer - * \param start start of the buffer (for bounds-checking) - * \param tag the tag to write + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param tag The tag to write. * - * \return the length written or a negative error code + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. */ int mbedtls_asn1_write_tag( unsigned char **p, unsigned char *start, - unsigned char tag ); + unsigned char tag ); /** - * \brief Write raw buffer data - * Note: function works backwards in data buffer + * \brief Write raw buffer data. * - * \param p reference to current position pointer - * \param start start of the buffer (for bounds-checking) - * \param buf data buffer to write - * \param size length of the data buffer + * \note This function works backwards in data buffer. * - * \return the length written or a negative error code + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param buf The data buffer to write. + * \param size The length of the data buffer. + * + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. */ int mbedtls_asn1_write_raw_buffer( unsigned char **p, unsigned char *start, - const unsigned char *buf, size_t size ); + const unsigned char *buf, size_t size ); #if defined(MBEDTLS_BIGNUM_C) /** - * \brief Write a big number (MBEDTLS_ASN1_INTEGER) in ASN.1 format - * Note: function works backwards in data buffer + * \brief Write a arbitrary-precision number (#MBEDTLS_ASN1_INTEGER) + * in ASN.1 format. + * + * \note This function works backwards in data buffer. * - * \param p reference to current position pointer - * \param start start of the buffer (for bounds-checking) - * \param X the MPI to write + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param X The MPI to write. * - * \return the length written or a negative error code + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. */ -int mbedtls_asn1_write_mpi( unsigned char **p, unsigned char *start, const mbedtls_mpi *X ); +int mbedtls_asn1_write_mpi( unsigned char **p, unsigned char *start, + const mbedtls_mpi *X ); #endif /* MBEDTLS_BIGNUM_C */ /** - * \brief Write a NULL tag (MBEDTLS_ASN1_NULL) with zero data in ASN.1 format - * Note: function works backwards in data buffer + * \brief Write a NULL tag (#MBEDTLS_ASN1_NULL) with zero data + * in ASN.1 format. + * + * \note This function works backwards in data buffer. * - * \param p reference to current position pointer - * \param start start of the buffer (for bounds-checking) + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. * - * \return the length written or a negative error code + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. */ int mbedtls_asn1_write_null( unsigned char **p, unsigned char *start ); /** - * \brief Write an OID tag (MBEDTLS_ASN1_OID) and data in ASN.1 format - * Note: function works backwards in data buffer + * \brief Write an OID tag (#MBEDTLS_ASN1_OID) and data + * in ASN.1 format. * - * \param p reference to current position pointer - * \param start start of the buffer (for bounds-checking) - * \param oid the OID to write - * \param oid_len length of the OID + * \note This function works backwards in data buffer. * - * \return the length written or a negative error code + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param oid The OID to write. + * \param oid_len The length of the OID. + * + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. */ int mbedtls_asn1_write_oid( unsigned char **p, unsigned char *start, - const char *oid, size_t oid_len ); + const char *oid, size_t oid_len ); /** - * \brief Write an AlgorithmIdentifier sequence in ASN.1 format - * Note: function works backwards in data buffer + * \brief Write an AlgorithmIdentifier sequence in ASN.1 format. + * + * \note This function works backwards in data buffer. * - * \param p reference to current position pointer - * \param start start of the buffer (for bounds-checking) - * \param oid the OID of the algorithm - * \param oid_len length of the OID - * \param par_len length of parameters, which must be already written. + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param oid The OID of the algorithm to write. + * \param oid_len The length of the algorithm's OID. + * \param par_len The length of the parameters, which must be already written. * If 0, NULL parameters are added * - * \return the length written or a negative error code + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. */ -int mbedtls_asn1_write_algorithm_identifier( unsigned char **p, unsigned char *start, - const char *oid, size_t oid_len, - size_t par_len ); +int mbedtls_asn1_write_algorithm_identifier( unsigned char **p, + unsigned char *start, + const char *oid, size_t oid_len, + size_t par_len ); /** - * \brief Write a boolean tag (MBEDTLS_ASN1_BOOLEAN) and value in ASN.1 format - * Note: function works backwards in data buffer + * \brief Write a boolean tag (#MBEDTLS_ASN1_BOOLEAN) and value + * in ASN.1 format. + * + * \note This function works backwards in data buffer. * - * \param p reference to current position pointer - * \param start start of the buffer (for bounds-checking) - * \param boolean 0 or 1 + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param boolean The boolean value to write, either \c 0 or \c 1. * - * \return the length written or a negative error code + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. */ -int mbedtls_asn1_write_bool( unsigned char **p, unsigned char *start, int boolean ); +int mbedtls_asn1_write_bool( unsigned char **p, unsigned char *start, + int boolean ); /** - * \brief Write an int tag (MBEDTLS_ASN1_INTEGER) and value in ASN.1 format - * Note: function works backwards in data buffer + * \brief Write an int tag (#MBEDTLS_ASN1_INTEGER) and value + * in ASN.1 format. * - * \param p reference to current position pointer - * \param start start of the buffer (for bounds-checking) - * \param val the integer value + * \note This function works backwards in data buffer. * - * \return the length written or a negative error code + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param val The integer value to write. + * + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. */ int mbedtls_asn1_write_int( unsigned char **p, unsigned char *start, int val ); /** - * \brief Write a printable string tag (MBEDTLS_ASN1_PRINTABLE_STRING) and - * value in ASN.1 format - * Note: function works backwards in data buffer + * \brief Write a string in ASN.1 format using a specific + * string encoding tag. + + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param tag The string encoding tag to write, e.g. + * #MBEDTLS_ASN1_UTF8_STRING. + * \param text The string to write. + * \param text_len The length of \p text in bytes (which might + * be strictly larger than the number of characters). + * + * \return The number of bytes written to \p p on success. + * \return A negative error code on failure. + */ +int mbedtls_asn1_write_tagged_string( unsigned char **p, unsigned char *start, + int tag, const char *text, + size_t text_len ); + +/** + * \brief Write a string in ASN.1 format using the PrintableString + * string encoding tag (#MBEDTLS_ASN1_PRINTABLE_STRING). + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param text The string to write. + * \param text_len The length of \p text in bytes (which might + * be strictly larger than the number of characters). + * + * \return The number of bytes written to \p p on success. + * \return A negative error code on failure. + */ +int mbedtls_asn1_write_printable_string( unsigned char **p, + unsigned char *start, + const char *text, size_t text_len ); + +/** + * \brief Write a UTF8 string in ASN.1 format using the UTF8String + * string encoding tag (#MBEDTLS_ASN1_PRINTABLE_STRING). + * + * \note This function works backwards in data buffer. * - * \param p reference to current position pointer - * \param start start of the buffer (for bounds-checking) - * \param text the text to write - * \param text_len length of the text + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param text The string to write. + * \param text_len The length of \p text in bytes (which might + * be strictly larger than the number of characters). * - * \return the length written or a negative error code + * \return The number of bytes written to \p p on success. + * \return A negative error code on failure. */ -int mbedtls_asn1_write_printable_string( unsigned char **p, unsigned char *start, - const char *text, size_t text_len ); +int mbedtls_asn1_write_utf8_string( unsigned char **p, unsigned char *start, + const char *text, size_t text_len ); /** - * \brief Write an IA5 string tag (MBEDTLS_ASN1_IA5_STRING) and - * value in ASN.1 format - * Note: function works backwards in data buffer + * \brief Write a string in ASN.1 format using the IA5String + * string encoding tag (#MBEDTLS_ASN1_IA5_STRING). * - * \param p reference to current position pointer - * \param start start of the buffer (for bounds-checking) - * \param text the text to write - * \param text_len length of the text + * \note This function works backwards in data buffer. * - * \return the length written or a negative error code + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param text The string to write. + * \param text_len The length of \p text in bytes (which might + * be strictly larger than the number of characters). + * + * \return The number of bytes written to \p p on success. + * \return A negative error code on failure. */ int mbedtls_asn1_write_ia5_string( unsigned char **p, unsigned char *start, - const char *text, size_t text_len ); + const char *text, size_t text_len ); /** - * \brief Write a bitstring tag (MBEDTLS_ASN1_BIT_STRING) and - * value in ASN.1 format - * Note: function works backwards in data buffer + * \brief Write a bitstring tag (#MBEDTLS_ASN1_BIT_STRING) and + * value in ASN.1 format. + * + * \note This function works backwards in data buffer. * - * \param p reference to current position pointer - * \param start start of the buffer (for bounds-checking) - * \param buf the bitstring - * \param bits the total number of bits in the bitstring + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param buf The bitstring to write. + * \param bits The total number of bits in the bitstring. * - * \return the length written or a negative error code + * \return The number of bytes written to \p p on success. + * \return A negative error code on failure. */ int mbedtls_asn1_write_bitstring( unsigned char **p, unsigned char *start, - const unsigned char *buf, size_t bits ); + const unsigned char *buf, size_t bits ); /** - * \brief Write an octet string tag (MBEDTLS_ASN1_OCTET_STRING) and - * value in ASN.1 format - * Note: function works backwards in data buffer + * \brief Write an octet string tag (#MBEDTLS_ASN1_OCTET_STRING) + * and value in ASN.1 format. + * + * \note This function works backwards in data buffer. * - * \param p reference to current position pointer - * \param start start of the buffer (for bounds-checking) - * \param buf data buffer to write - * \param size length of the data buffer + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param buf The buffer holding the data to write. + * \param size The length of the data buffer \p buf. * - * \return the length written or a negative error code + * \return The number of bytes written to \p p on success. + * \return A negative error code on failure. */ int mbedtls_asn1_write_octet_string( unsigned char **p, unsigned char *start, - const unsigned char *buf, size_t size ); + const unsigned char *buf, size_t size ); /** * \brief Create or find a specific named_data entry for writing in a @@ -218,15 +299,16 @@ int mbedtls_asn1_write_octet_string( unsigned char **p, unsigned char *start, * a new entry is added to the head of the list. * Warning: Destructive behaviour for the val data! * - * \param list Pointer to the location of the head of the list to seek - * through (will be updated in case of a new entry) - * \param oid The OID to look for - * \param oid_len Size of the OID - * \param val Data to store (can be NULL if you want to fill it by hand) - * \param val_len Minimum length of the data buffer needed + * \param list The pointer to the location of the head of the list to seek + * through (will be updated in case of a new entry). + * \param oid The OID to look for. + * \param oid_len The size of the OID. + * \param val The data to store (can be \c NULL if you want to fill + * it by hand). + * \param val_len The minimum length of the data buffer needed. * - * \return NULL if if there was a memory allocation error, or a pointer - * to the new / existing entry. + * \return A pointer to the new / existing entry on success. + * \return \c NULL if if there was a memory allocation error. */ mbedtls_asn1_named_data *mbedtls_asn1_store_named_data( mbedtls_asn1_named_data **list, const char *oid, size_t oid_len, diff --git a/thirdparty/mbedtls/include/mbedtls/bignum.h b/thirdparty/mbedtls/include/mbedtls/bignum.h index 31383b1eb5..141a8e9adf 100644 --- a/thirdparty/mbedtls/include/mbedtls/bignum.h +++ b/thirdparty/mbedtls/include/mbedtls/bignum.h @@ -177,7 +177,7 @@ extern "C" { /** * \brief MPI structure */ -typedef struct +typedef struct mbedtls_mpi { int s; /*!< integer sign */ size_t n; /*!< total # of limbs */ @@ -186,96 +186,115 @@ typedef struct mbedtls_mpi; /** - * \brief Initialize one MPI (make internal references valid) - * This just makes it ready to be set or freed, + * \brief Initialize an MPI context. + * + * This makes the MPI ready to be set or freed, * but does not define a value for the MPI. * - * \param X One MPI to initialize. + * \param X The MPI context to initialize. This must not be \c NULL. */ void mbedtls_mpi_init( mbedtls_mpi *X ); /** - * \brief Unallocate one MPI + * \brief This function frees the components of an MPI context. * - * \param X One MPI to unallocate. + * \param X The MPI context to be cleared. This may be \c NULL, + * in which case this function is a no-op. If it is + * not \c NULL, it must point to an initialized MPI. */ void mbedtls_mpi_free( mbedtls_mpi *X ); /** - * \brief Enlarge to the specified number of limbs + * \brief Enlarge an MPI to the specified number of limbs. * - * This function does nothing if the MPI is already large enough. + * \note This function does nothing if the MPI is + * already large enough. * - * \param X MPI to grow - * \param nblimbs The target number of limbs + * \param X The MPI to grow. It must be initialized. + * \param nblimbs The target number of limbs. * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return Another negative error code on other kinds of failure. */ int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs ); /** - * \brief Resize down, keeping at least the specified number of limbs + * \brief This function resizes an MPI downwards, keeping at least the + * specified number of limbs. * * If \c X is smaller than \c nblimbs, it is resized up * instead. * - * \param X MPI to shrink - * \param nblimbs The minimum number of limbs to keep + * \param X The MPI to shrink. This must point to an initialized MPI. + * \param nblimbs The minimum number of limbs to keep. * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed * (this can only happen when resizing up). + * \return Another negative error code on other kinds of failure. */ int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs ); /** - * \brief Copy the contents of Y into X + * \brief Make a copy of an MPI. + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param Y The source MPI. This must point to an initialized MPI. * - * \param X Destination MPI. It is enlarged if necessary. - * \param Y Source MPI. + * \note The limb-buffer in the destination MPI is enlarged + * if necessary to hold the value in the source MPI. * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return Another negative error code on other kinds of failure. */ int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y ); /** - * \brief Swap the contents of X and Y + * \brief Swap the contents of two MPIs. * - * \param X First MPI value - * \param Y Second MPI value + * \param X The first MPI. It must be initialized. + * \param Y The second MPI. It must be initialized. */ void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y ); /** - * \brief Safe conditional assignement X = Y if assign is 1 + * \brief Perform a safe conditional copy of MPI which doesn't + * reveal whether the condition was true or not. * - * \param X MPI to conditionally assign to - * \param Y Value to be assigned - * \param assign 1: perform the assignment, 0: keep X's original value - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * \param X The MPI to conditionally assign to. This must point + * to an initialized MPI. + * \param Y The MPI to be assigned from. This must point to an + * initialized MPI. + * \param assign The condition deciding whether to perform the + * assignment or not. Possible values: + * * \c 1: Perform the assignment `X = Y`. + * * \c 0: Keep the original value of \p X. * * \note This function is equivalent to - * if( assign ) mbedtls_mpi_copy( X, Y ); + * `if( assign ) mbedtls_mpi_copy( X, Y );` * except that it avoids leaking any information about whether * the assignment was done or not (the above code may leak * information through branch prediction and/or memory access * patterns analysis). + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return Another negative error code on other kinds of failure. */ int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign ); /** - * \brief Safe conditional swap X <-> Y if swap is 1 + * \brief Perform a safe conditional swap which doesn't + * reveal whether the condition was true or not. * - * \param X First mbedtls_mpi value - * \param Y Second mbedtls_mpi value - * \param assign 1: perform the swap, 0: keep X and Y's original values - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * \param X The first MPI. This must be initialized. + * \param Y The second MPI. This must be initialized. + * \param assign The condition deciding whether to perform + * the swap or not. Possible values: + * * \c 1: Swap the values of \p X and \p Y. + * * \c 0: Keep the original values of \p X and \p Y. * * \note This function is equivalent to * if( assign ) mbedtls_mpi_swap( X, Y ); @@ -283,415 +302,512 @@ int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned * the assignment was done or not (the above code may leak * information through branch prediction and/or memory access * patterns analysis). + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return Another negative error code on other kinds of failure. + * */ int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char assign ); /** - * \brief Set value from integer + * \brief Store integer value in MPI. * - * \param X MPI to set - * \param z Value to use + * \param X The MPI to set. This must be initialized. + * \param z The value to use. * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return Another negative error code on other kinds of failure. */ int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z ); /** - * \brief Get a specific bit from X + * \brief Get a specific bit from an MPI. * - * \param X MPI to use - * \param pos Zero-based index of the bit in X + * \param X The MPI to query. This must be initialized. + * \param pos Zero-based index of the bit to query. * - * \return Either a 0 or a 1 + * \return \c 0 or \c 1 on success, depending on whether bit \c pos + * of \c X is unset or set. + * \return A negative error code on failure. */ int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos ); /** - * \brief Set a bit of X to a specific value of 0 or 1 + * \brief Modify a specific bit in an MPI. * - * \note Will grow X if necessary to set a bit to 1 in a not yet - * existing limb. Will not grow if bit should be set to 0 + * \note This function will grow the target MPI if necessary to set a + * bit to \c 1 in a not yet existing limb. It will not grow if + * the bit should be set to \c 0. * - * \param X MPI to use - * \param pos Zero-based index of the bit in X - * \param val The value to set the bit to (0 or 1) + * \param X The MPI to modify. This must be initialized. + * \param pos Zero-based index of the bit to modify. + * \param val The desired value of bit \c pos: \c 0 or \c 1. * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, - * MBEDTLS_ERR_MPI_BAD_INPUT_DATA if val is not 0 or 1 + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return Another negative error code on other kinds of failure. */ int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val ); /** - * \brief Return the number of zero-bits before the least significant - * '1' bit + * \brief Return the number of bits of value \c 0 before the + * least significant bit of value \c 1. + * + * \note This is the same as the zero-based index of + * the least significant bit of value \c 1. * - * Note: Thus also the zero-based index of the least significant '1' bit + * \param X The MPI to query. * - * \param X MPI to use + * \return The number of bits of value \c 0 before the least significant + * bit of value \c 1 in \p X. */ size_t mbedtls_mpi_lsb( const mbedtls_mpi *X ); /** * \brief Return the number of bits up to and including the most - * significant '1' bit' + * significant bit of value \c 1. * - * Note: Thus also the one-based index of the most significant '1' bit + * * \note This is same as the one-based index of the most + * significant bit of value \c 1. * - * \param X MPI to use + * \param X The MPI to query. This must point to an initialized MPI. + * + * \return The number of bits up to and including the most + * significant bit of value \c 1. */ size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X ); /** - * \brief Return the total size in bytes + * \brief Return the total size of an MPI value in bytes. + * + * \param X The MPI to use. This must point to an initialized MPI. * - * \param X MPI to use + * \note The value returned by this function may be less than + * the number of bytes used to store \p X internally. + * This happens if and only if there are trailing bytes + * of value zero. + * + * \return The least number of bytes capable of storing + * the absolute value of \p X. */ size_t mbedtls_mpi_size( const mbedtls_mpi *X ); /** - * \brief Import from an ASCII string + * \brief Import an MPI from an ASCII string. * - * \param X Destination MPI - * \param radix Input numeric base - * \param s Null-terminated string buffer + * \param X The destination MPI. This must point to an initialized MPI. + * \param radix The numeric base of the input string. + * \param s Null-terminated string buffer. * - * \return 0 if successful, or a MBEDTLS_ERR_MPI_XXX error code + * \return \c 0 if successful. + * \return A negative error code on failure. */ int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s ); /** - * \brief Export into an ASCII string + * \brief Export an MPI to an ASCII string. * - * \param X Source MPI - * \param radix Output numeric base - * \param buf Buffer to write the string to - * \param buflen Length of buf - * \param olen Length of the string written, including final NUL byte + * \param X The source MPI. This must point to an initialized MPI. + * \param radix The numeric base of the output string. + * \param buf The buffer to write the string to. This must be writable + * buffer of length \p buflen Bytes. + * \param buflen The available size in Bytes of \p buf. + * \param olen The address at which to store the length of the string + * written, including the final \c NULL byte. This must + * not be \c NULL. * - * \return 0 if successful, or a MBEDTLS_ERR_MPI_XXX error code. - * *olen is always updated to reflect the amount - * of data that has (or would have) been written. + * \note You can call this function with `buflen == 0` to obtain the + * minimum required buffer size in `*olen`. * - * \note Call this function with buflen = 0 to obtain the - * minimum required buffer size in *olen. + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if the target buffer \p buf + * is too small to hold the value of \p X in the desired base. + * In this case, `*olen` is nonetheless updated to contain the + * size of \p buf required for a successful call. + * \return Another negative error code on different kinds of failure. */ int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix, char *buf, size_t buflen, size_t *olen ); #if defined(MBEDTLS_FS_IO) /** - * \brief Read MPI from a line in an opened file - * - * \param X Destination MPI - * \param radix Input numeric base - * \param fin Input file handle + * \brief Read an MPI from a line in an opened file. * - * \return 0 if successful, MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if - * the file read buffer is too small or a - * MBEDTLS_ERR_MPI_XXX error code + * \param X The destination MPI. This must point to an initialized MPI. + * \param radix The numeric base of the string representation used + * in the source line. + * \param fin The input file handle to use. This must not be \c NULL. * * \note On success, this function advances the file stream * to the end of the current line or to EOF. * - * The function returns 0 on an empty line. + * The function returns \c 0 on an empty line. * * Leading whitespaces are ignored, as is a - * '0x' prefix for radix 16. + * '0x' prefix for radix \c 16. * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if the file read buffer + * is too small. + * \return Another negative error code on failure. */ int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin ); /** - * \brief Write X into an opened file, or stdout if fout is NULL + * \brief Export an MPI into an opened file. * - * \param p Prefix, can be NULL - * \param X Source MPI - * \param radix Output numeric base - * \param fout Output file handle (can be NULL) + * \param p A string prefix to emit prior to the MPI data. + * For example, this might be a label, or "0x" when + * printing in base \c 16. This may be \c NULL if no prefix + * is needed. + * \param X The source MPI. This must point to an initialized MPI. + * \param radix The numeric base to be used in the emitted string. + * \param fout The output file handle. This may be \c NULL, in which case + * the output is written to \c stdout. * - * \return 0 if successful, or a MBEDTLS_ERR_MPI_XXX error code - * - * \note Set fout == NULL to print X on the console. + * \return \c 0 if successful. + * \return A negative error code on failure. */ -int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout ); +int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, + int radix, FILE *fout ); #endif /* MBEDTLS_FS_IO */ /** - * \brief Import X from unsigned binary data, big endian + * \brief Import an MPI from unsigned big endian binary data. * - * \param X Destination MPI - * \param buf Input buffer - * \param buflen Input buffer size + * \param X The destination MPI. This must point to an initialized MPI. + * \param buf The input buffer. This must be a readable buffer of length + * \p buflen Bytes. + * \param buflen The length of the input buffer \p p in Bytes. * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return Another negative error code on different kinds of failure. */ -int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen ); +int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, + size_t buflen ); /** - * \brief Export X into unsigned binary data, big endian. - * Always fills the whole buffer, which will start with zeros - * if the number is smaller. + * \brief Export an MPI into unsigned big endian binary data + * of fixed size. * - * \param X Source MPI - * \param buf Output buffer - * \param buflen Output buffer size + * \param X The source MPI. This must point to an initialized MPI. + * \param buf The output buffer. This must be a writable buffer of length + * \p buflen Bytes. + * \param buflen The size of the output buffer \p buf in Bytes. * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if buf isn't large enough + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p buf isn't + * large enough to hold the value of \p X. + * \return Another negative error code on different kinds of failure. */ -int mbedtls_mpi_write_binary( const mbedtls_mpi *X, unsigned char *buf, size_t buflen ); +int mbedtls_mpi_write_binary( const mbedtls_mpi *X, unsigned char *buf, + size_t buflen ); /** - * \brief Left-shift: X <<= count + * \brief Perform a left-shift on an MPI: X <<= count * - * \param X MPI to shift - * \param count Amount to shift + * \param X The MPI to shift. This must point to an initialized MPI. + * \param count The number of bits to shift by. * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. */ int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count ); /** - * \brief Right-shift: X >>= count + * \brief Perform a right-shift on an MPI: X >>= count * - * \param X MPI to shift - * \param count Amount to shift + * \param X The MPI to shift. This must point to an initialized MPI. + * \param count The number of bits to shift by. * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. */ int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count ); /** - * \brief Compare unsigned values + * \brief Compare the absolute values of two MPIs. * - * \param X Left-hand MPI - * \param Y Right-hand MPI + * \param X The left-hand MPI. This must point to an initialized MPI. + * \param Y The right-hand MPI. This must point to an initialized MPI. * - * \return 1 if |X| is greater than |Y|, - * -1 if |X| is lesser than |Y| or - * 0 if |X| is equal to |Y| + * \return \c 1 if `|X|` is greater than `|Y|`. + * \return \c -1 if `|X|` is lesser than `|Y|`. + * \return \c 0 if `|X|` is equal to `|Y|`. */ int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y ); /** - * \brief Compare signed values + * \brief Compare two MPIs. * - * \param X Left-hand MPI - * \param Y Right-hand MPI + * \param X The left-hand MPI. This must point to an initialized MPI. + * \param Y The right-hand MPI. This must point to an initialized MPI. * - * \return 1 if X is greater than Y, - * -1 if X is lesser than Y or - * 0 if X is equal to Y + * \return \c 1 if \p X is greater than \p Y. + * \return \c -1 if \p X is lesser than \p Y. + * \return \c 0 if \p X is equal to \p Y. */ int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y ); /** - * \brief Compare signed values + * \brief Compare an MPI with an integer. * - * \param X Left-hand MPI - * \param z The integer value to compare to + * \param X The left-hand MPI. This must point to an initialized MPI. + * \param z The integer value to compare \p X to. * - * \return 1 if X is greater than z, - * -1 if X is lesser than z or - * 0 if X is equal to z + * \return \c 1 if \p X is greater than \p z. + * \return \c -1 if \p X is lesser than \p z. + * \return \c 0 if \p X is equal to \p z. */ int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z ); /** - * \brief Unsigned addition: X = |A| + |B| + * \brief Perform an unsigned addition of MPIs: X = |A| + |B| * - * \param X Destination MPI - * \param A Left-hand MPI - * \param B Right-hand MPI + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The first summand. This must point to an initialized MPI. + * \param B The second summand. This must point to an initialized MPI. * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. */ -int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ); +int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *B ); /** - * \brief Unsigned subtraction: X = |A| - |B| + * \brief Perform an unsigned subtraction of MPIs: X = |A| - |B| + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The minuend. This must point to an initialized MPI. + * \param B The subtrahend. This must point to an initialized MPI. * - * \param X Destination MPI - * \param A Left-hand MPI - * \param B Right-hand MPI + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_NEGATIVE_VALUE if \p B is greater than \p A. + * \return Another negative error code on different kinds of failure. * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_NEGATIVE_VALUE if B is greater than A */ -int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ); +int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *B ); /** - * \brief Signed addition: X = A + B + * \brief Perform a signed addition of MPIs: X = A + B * - * \param X Destination MPI - * \param A Left-hand MPI - * \param B Right-hand MPI + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The first summand. This must point to an initialized MPI. + * \param B The second summand. This must point to an initialized MPI. * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. */ -int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ); +int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *B ); /** - * \brief Signed subtraction: X = A - B + * \brief Perform a signed subtraction of MPIs: X = A - B * - * \param X Destination MPI - * \param A Left-hand MPI - * \param B Right-hand MPI + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The minuend. This must point to an initialized MPI. + * \param B The subtrahend. This must point to an initialized MPI. * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. */ -int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ); +int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *B ); /** - * \brief Signed addition: X = A + b + * \brief Perform a signed addition of an MPI and an integer: X = A + b * - * \param X Destination MPI - * \param A Left-hand MPI - * \param b The integer value to add + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The first summand. This must point to an initialized MPI. + * \param b The second summand. * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. */ -int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b ); +int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, + mbedtls_mpi_sint b ); /** - * \brief Signed subtraction: X = A - b + * \brief Perform a signed subtraction of an MPI and an integer: + * X = A - b * - * \param X Destination MPI - * \param A Left-hand MPI - * \param b The integer value to subtract + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The minuend. This must point to an initialized MPI. + * \param b The subtrahend. * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. */ -int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b ); +int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, + mbedtls_mpi_sint b ); /** - * \brief Baseline multiplication: X = A * B + * \brief Perform a multiplication of two MPIs: X = A * B + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The first factor. This must point to an initialized MPI. + * \param B The second factor. This must point to an initialized MPI. * - * \param X Destination MPI - * \param A Left-hand MPI - * \param B Right-hand MPI + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed */ -int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ); +int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *B ); /** - * \brief Baseline multiplication: X = A * b + * \brief Perform a multiplication of an MPI with an unsigned integer: + * X = A * b * - * \param X Destination MPI - * \param A Left-hand MPI - * \param b The unsigned integer value to multiply with + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The first factor. This must point to an initialized MPI. + * \param b The second factor. * - * \note b is unsigned + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed */ -int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b ); +int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, + mbedtls_mpi_uint b ); /** - * \brief Division by mbedtls_mpi: A = Q * B + R + * \brief Perform a division with remainder of two MPIs: + * A = Q * B + R * - * \param Q Destination MPI for the quotient - * \param R Destination MPI for the rest value - * \param A Left-hand MPI - * \param B Right-hand MPI + * \param Q The destination MPI for the quotient. + * This may be \c NULL if the value of the + * quotient is not needed. + * \param R The destination MPI for the remainder value. + * This may be \c NULL if the value of the + * remainder is not needed. + * \param A The dividend. This must point to an initialized MPi. + * \param B The divisor. This must point to an initialized MPI. * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, - * MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if B == 0 - * - * \note Either Q or R can be NULL. + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return #MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if \p B equals zero. + * \return Another negative error code on different kinds of failure. */ -int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B ); +int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, + const mbedtls_mpi *B ); /** - * \brief Division by int: A = Q * b + R - * - * \param Q Destination MPI for the quotient - * \param R Destination MPI for the rest value - * \param A Left-hand MPI - * \param b Integer to divide by + * \brief Perform a division with remainder of an MPI by an integer: + * A = Q * b + R * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, - * MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if b == 0 + * \param Q The destination MPI for the quotient. + * This may be \c NULL if the value of the + * quotient is not needed. + * \param R The destination MPI for the remainder value. + * This may be \c NULL if the value of the + * remainder is not needed. + * \param A The dividend. This must point to an initialized MPi. + * \param b The divisor. * - * \note Either Q or R can be NULL. + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return #MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if \p b equals zero. + * \return Another negative error code on different kinds of failure. */ -int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, mbedtls_mpi_sint b ); +int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, + mbedtls_mpi_sint b ); /** - * \brief Modulo: R = A mod B + * \brief Perform a modular reduction. R = A mod B * - * \param R Destination MPI for the rest value - * \param A Left-hand MPI - * \param B Right-hand MPI + * \param R The destination MPI for the residue value. + * This must point to an initialized MPI. + * \param A The MPI to compute the residue of. + * This must point to an initialized MPI. + * \param B The base of the modular reduction. + * This must point to an initialized MPI. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return #MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if \p B equals zero. + * \return #MBEDTLS_ERR_MPI_NEGATIVE_VALUE if \p B is negative. + * \return Another negative error code on different kinds of failure. * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, - * MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if B == 0, - * MBEDTLS_ERR_MPI_NEGATIVE_VALUE if B < 0 */ -int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B ); +int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, + const mbedtls_mpi *B ); /** - * \brief Modulo: r = A mod b + * \brief Perform a modular reduction with respect to an integer. + * r = A mod b * - * \param r Destination mbedtls_mpi_uint - * \param A Left-hand MPI - * \param b Integer to divide by + * \param r The address at which to store the residue. + * This must not be \c NULL. + * \param A The MPI to compute the residue of. + * This must point to an initialized MPi. + * \param b The integer base of the modular reduction. * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, - * MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if b == 0, - * MBEDTLS_ERR_MPI_NEGATIVE_VALUE if b < 0 + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return #MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if \p b equals zero. + * \return #MBEDTLS_ERR_MPI_NEGATIVE_VALUE if \p b is negative. + * \return Another negative error code on different kinds of failure. */ -int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b ); +int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, + mbedtls_mpi_sint b ); /** - * \brief Sliding-window exponentiation: X = A^E mod N - * - * \param X Destination MPI - * \param A Left-hand MPI - * \param E Exponent MPI - * \param N Modular MPI - * \param _RR Speed-up MPI used for recalculations + * \brief Perform a sliding-window exponentiation: X = A^E mod N * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, - * MBEDTLS_ERR_MPI_BAD_INPUT_DATA if N is negative or even or - * if E is negative + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The base of the exponentiation. + * This must point to an initialized MPI. + * \param E The exponent MPI. This must point to an initialized MPI. + * \param N The base for the modular reduction. This must point to an + * initialized MPI. + * \param _RR A helper MPI depending solely on \p N which can be used to + * speed-up multiple modular exponentiations for the same value + * of \p N. This may be \c NULL. If it is not \c NULL, it must + * point to an initialized MPI. If it hasn't been used after + * the call to mbedtls_mpi_init(), this function will compute + * the helper value and store it in \p _RR for reuse on + * subsequent calls to this function. Otherwise, the function + * will assume that \p _RR holds the helper value set by a + * previous call to mbedtls_mpi_exp_mod(), and reuse it. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \c N is negative or + * even, or if \c E is negative. + * \return Another negative error code on different kinds of failures. * - * \note _RR is used to avoid re-computing R*R mod N across - * multiple calls, which speeds up things a bit. It can - * be set to NULL if the extra performance is unneeded. */ -int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *E, const mbedtls_mpi *N, mbedtls_mpi *_RR ); +int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *E, const mbedtls_mpi *N, + mbedtls_mpi *_RR ); /** - * \brief Fill an MPI X with size bytes of random + * \brief Fill an MPI with a number of random bytes. * - * \param X Destination MPI - * \param size Size in bytes - * \param f_rng RNG function - * \param p_rng RNG parameter + * \param X The destination MPI. This must point to an initialized MPI. + * \param size The number of random bytes to generate. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. This may be + * \c NULL if \p f_rng doesn't need a context argument. * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on failure. * - * \note The bytes obtained from the PRNG are interpreted + * \note The bytes obtained from the RNG are interpreted * as a big-endian representation of an MPI; this can * be relevant in applications like deterministic ECDSA. */ @@ -700,61 +816,130 @@ int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size, void *p_rng ); /** - * \brief Greatest common divisor: G = gcd(A, B) - * - * \param G Destination MPI - * \param A Left-hand MPI - * \param B Right-hand MPI - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed - */ -int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B ); - -/** - * \brief Modular inverse: X = A^-1 mod N + * \brief Compute the greatest common divisor: G = gcd(A, B) * - * \param X Destination MPI - * \param A Left-hand MPI - * \param N Right-hand MPI + * \param G The destination MPI. This must point to an initialized MPI. + * \param A The first operand. This must point to an initialized MPI. + * \param B The second operand. This must point to an initialized MPI. * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, - * MBEDTLS_ERR_MPI_BAD_INPUT_DATA if N is <= 1, - MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if A has no inverse mod N. + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. */ -int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N ); +int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, + const mbedtls_mpi *B ); /** - * \brief Miller-Rabin primality test + * \brief Compute the modular inverse: X = A^-1 mod N * - * \param X MPI to check - * \param f_rng RNG function - * \param p_rng RNG parameter + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The MPI to calculate the modular inverse of. This must point + * to an initialized MPI. + * \param N The base of the modular inversion. This must point to an + * initialized MPI. * - * \return 0 if successful (probably prime), - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, - * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if X is not prime + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p N is less than + * or equal to one. + * \return #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if \p has no modular inverse + * with respect to \p N. */ -int mbedtls_mpi_is_prime( const mbedtls_mpi *X, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); +int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *N ); +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif /** - * \brief Prime number generation - * - * \param X Destination MPI - * \param nbits Required size of X in bits - * ( 3 <= nbits <= MBEDTLS_MPI_MAX_BITS ) - * \param dh_flag If 1, then (X-1)/2 will be prime too - * \param f_rng RNG function - * \param p_rng RNG parameter - * - * \return 0 if successful (probably prime), - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, - * MBEDTLS_ERR_MPI_BAD_INPUT_DATA if nbits is < 3 - */ -int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag, + * \brief Perform a Miller-Rabin primality test with error + * probability of 2<sup>-80</sup>. + * + * \deprecated Superseded by mbedtls_mpi_is_prime_ext() which allows + * specifying the number of Miller-Rabin rounds. + * + * \param X The MPI to check for primality. + * This must point to an initialized MPI. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. + * This may be \c NULL if \p f_rng doesn't use a + * context parameter. + * + * \return \c 0 if successful, i.e. \p X is probably prime. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if \p X is not prime. + * \return Another negative error code on other kinds of failure. + */ +MBEDTLS_DEPRECATED int mbedtls_mpi_is_prime( const mbedtls_mpi *X, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief Miller-Rabin primality test. + * + * \warning If \p X is potentially generated by an adversary, for example + * when validating cryptographic parameters that you didn't + * generate yourself and that are supposed to be prime, then + * \p rounds should be at least the half of the security + * strength of the cryptographic algorithm. On the other hand, + * if \p X is chosen uniformly or non-adversially (as is the + * case when mbedtls_mpi_gen_prime calls this function), then + * \p rounds can be much lower. + * + * \param X The MPI to check for primality. + * This must point to an initialized MPI. + * \param rounds The number of bases to perform the Miller-Rabin primality + * test for. The probability of returning 0 on a composite is + * at most 2<sup>-2*\p rounds</sup>. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. + * This may be \c NULL if \p f_rng doesn't use + * a context parameter. + * + * \return \c 0 if successful, i.e. \p X is probably prime. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if \p X is not prime. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); +/** + * \brief Flags for mbedtls_mpi_gen_prime() + * + * Each of these flags is a constraint on the result X returned by + * mbedtls_mpi_gen_prime(). + */ +typedef enum { + MBEDTLS_MPI_GEN_PRIME_FLAG_DH = 0x0001, /**< (X-1)/2 is prime too */ + MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR = 0x0002, /**< lower error rate from 2<sup>-80</sup> to 2<sup>-128</sup> */ +} mbedtls_mpi_gen_prime_flag_t; + +/** + * \brief Generate a prime number. + * + * \param X The destination MPI to store the generated prime in. + * This must point to an initialized MPi. + * \param nbits The required size of the destination MPI in bits. + * This must be between \c 3 and #MBEDTLS_MPI_MAX_BITS. + * \param flags A mask of flags of type #mbedtls_mpi_gen_prime_flag_t. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. + * This may be \c NULL if \p f_rng doesn't use + * a context parameter. + * + * \return \c 0 if successful, in which case \p X holds a + * probably prime number. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if `nbits` is not between + * \c 3 and #MBEDTLS_MPI_MAX_BITS. + */ +int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); diff --git a/thirdparty/mbedtls/include/mbedtls/blowfish.h b/thirdparty/mbedtls/include/mbedtls/blowfish.h index 985faa43f0..f01573dcaf 100644 --- a/thirdparty/mbedtls/include/mbedtls/blowfish.h +++ b/thirdparty/mbedtls/include/mbedtls/blowfish.h @@ -33,6 +33,8 @@ #include <stddef.h> #include <stdint.h> +#include "platform_util.h" + #define MBEDTLS_BLOWFISH_ENCRYPT 1 #define MBEDTLS_BLOWFISH_DECRYPT 0 #define MBEDTLS_BLOWFISH_MAX_KEY_BITS 448 @@ -40,9 +42,16 @@ #define MBEDTLS_BLOWFISH_ROUNDS 16 /**< Rounds to use. When increasing this value, make sure to extend the initialisation vectors */ #define MBEDTLS_BLOWFISH_BLOCKSIZE 8 /* Blowfish uses 64 bit blocks */ -#define MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH -0x0016 /**< Invalid key length. */ +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#define MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH MBEDTLS_DEPRECATED_NUMERIC_CONSTANT( -0x0016 ) +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ +#define MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA -0x0016 /**< Bad input data. */ + +#define MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH -0x0018 /**< Invalid data input length. */ + +/* MBEDTLS_ERR_BLOWFISH_HW_ACCEL_FAILED is deprecated and should not be used. + */ #define MBEDTLS_ERR_BLOWFISH_HW_ACCEL_FAILED -0x0017 /**< Blowfish hardware accelerator failed. */ -#define MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH -0x0018 /**< Invalid data input length. */ #ifdef __cplusplus extern "C" { @@ -55,7 +64,7 @@ extern "C" { /** * \brief Blowfish context structure */ -typedef struct +typedef struct mbedtls_blowfish_context { uint32_t P[MBEDTLS_BLOWFISH_ROUNDS + 2]; /*!< Blowfish round keys */ uint32_t S[4][256]; /*!< key dependent S-boxes */ @@ -67,40 +76,53 @@ mbedtls_blowfish_context; #endif /* MBEDTLS_BLOWFISH_ALT */ /** - * \brief Initialize Blowfish context + * \brief Initialize a Blowfish context. * - * \param ctx Blowfish context to be initialized + * \param ctx The Blowfish context to be initialized. + * This must not be \c NULL. */ void mbedtls_blowfish_init( mbedtls_blowfish_context *ctx ); /** - * \brief Clear Blowfish context + * \brief Clear a Blowfish context. * - * \param ctx Blowfish context to be cleared + * \param ctx The Blowfish context to be cleared. + * This may be \c NULL, in which case this function + * returns immediately. If it is not \c NULL, it must + * point to an initialized Blowfish context. */ void mbedtls_blowfish_free( mbedtls_blowfish_context *ctx ); /** - * \brief Blowfish key schedule + * \brief Perform a Blowfish key schedule operation. * - * \param ctx Blowfish context to be initialized - * \param key encryption key - * \param keybits must be between 32 and 448 bits + * \param ctx The Blowfish context to perform the key schedule on. + * \param key The encryption key. This must be a readable buffer of + * length \p keybits Bits. + * \param keybits The length of \p key in Bits. This must be between + * \c 32 and \c 448 and a multiple of \c 8. * - * \return 0 if successful, or MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH + * \return \c 0 if successful. + * \return A negative error code on failure. */ int mbedtls_blowfish_setkey( mbedtls_blowfish_context *ctx, const unsigned char *key, unsigned int keybits ); /** - * \brief Blowfish-ECB block encryption/decryption + * \brief Perform a Blowfish-ECB block encryption/decryption operation. * - * \param ctx Blowfish context - * \param mode MBEDTLS_BLOWFISH_ENCRYPT or MBEDTLS_BLOWFISH_DECRYPT - * \param input 8-byte input block - * \param output 8-byte output block + * \param ctx The Blowfish context to use. This must be initialized + * and bound to a key. + * \param mode The mode of operation. Possible values are + * #MBEDTLS_BLOWFISH_ENCRYPT for encryption, or + * #MBEDTLS_BLOWFISH_DECRYPT for decryption. + * \param input The input block. This must be a readable buffer + * of size \c 8 Bytes. + * \param output The output block. This must be a writable buffer + * of size \c 8 Bytes. * - * \return 0 if successful + * \return \c 0 if successful. + * \return A negative error code on failure. */ int mbedtls_blowfish_crypt_ecb( mbedtls_blowfish_context *ctx, int mode, @@ -109,9 +131,7 @@ int mbedtls_blowfish_crypt_ecb( mbedtls_blowfish_context *ctx, #if defined(MBEDTLS_CIPHER_MODE_CBC) /** - * \brief Blowfish-CBC buffer encryption/decryption - * Length should be a multiple of the block - * size (8 bytes) + * \brief Perform a Blowfish-CBC buffer encryption/decryption operation. * * \note Upon exit, the content of the IV is updated so that you can * call the function same function again on the following @@ -121,15 +141,22 @@ int mbedtls_blowfish_crypt_ecb( mbedtls_blowfish_context *ctx, * IV, you should either save it manually or use the cipher * module instead. * - * \param ctx Blowfish context - * \param mode MBEDTLS_BLOWFISH_ENCRYPT or MBEDTLS_BLOWFISH_DECRYPT - * \param length length of the input data - * \param iv initialization vector (updated after use) - * \param input buffer holding the input data - * \param output buffer holding the output data + * \param ctx The Blowfish context to use. This must be initialized + * and bound to a key. + * \param mode The mode of operation. Possible values are + * #MBEDTLS_BLOWFISH_ENCRYPT for encryption, or + * #MBEDTLS_BLOWFISH_DECRYPT for decryption. + * \param length The length of the input data in Bytes. This must be + * multiple of \c 8. + * \param iv The initialization vector. This must be a read/write buffer + * of length \c 8 Bytes. It is updated by this function. + * \param input The input data. This must be a readable buffer of length + * \p length Bytes. + * \param output The output data. This must be a writable buffer of length + * \p length Bytes. * - * \return 0 if successful, or - * MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH + * \return \c 0 if successful. + * \return A negative error code on failure. */ int mbedtls_blowfish_crypt_cbc( mbedtls_blowfish_context *ctx, int mode, @@ -141,7 +168,7 @@ int mbedtls_blowfish_crypt_cbc( mbedtls_blowfish_context *ctx, #if defined(MBEDTLS_CIPHER_MODE_CFB) /** - * \brief Blowfish CFB buffer encryption/decryption. + * \brief Perform a Blowfish CFB buffer encryption/decryption operation. * * \note Upon exit, the content of the IV is updated so that you can * call the function same function again on the following @@ -151,15 +178,25 @@ int mbedtls_blowfish_crypt_cbc( mbedtls_blowfish_context *ctx, * IV, you should either save it manually or use the cipher * module instead. * - * \param ctx Blowfish context - * \param mode MBEDTLS_BLOWFISH_ENCRYPT or MBEDTLS_BLOWFISH_DECRYPT - * \param length length of the input data - * \param iv_off offset in IV (updated after use) - * \param iv initialization vector (updated after use) - * \param input buffer holding the input data - * \param output buffer holding the output data + * \param ctx The Blowfish context to use. This must be initialized + * and bound to a key. + * \param mode The mode of operation. Possible values are + * #MBEDTLS_BLOWFISH_ENCRYPT for encryption, or + * #MBEDTLS_BLOWFISH_DECRYPT for decryption. + * \param length The length of the input data in Bytes. + * \param iv_off The offset in the initialiation vector. + * The value pointed to must be smaller than \c 8 Bytes. + * It is updated by this function to support the aforementioned + * streaming usage. + * \param iv The initialization vector. This must be a read/write buffer + * of size \c 8 Bytes. It is updated after use. + * \param input The input data. This must be a readable buffer of length + * \p length Bytes. + * \param output The output data. This must be a writable buffer of length + * \p length Bytes. * - * \return 0 if successful + * \return \c 0 if successful. + * \return A negative error code on failure. */ int mbedtls_blowfish_crypt_cfb64( mbedtls_blowfish_context *ctx, int mode, @@ -172,7 +209,7 @@ int mbedtls_blowfish_crypt_cfb64( mbedtls_blowfish_context *ctx, #if defined(MBEDTLS_CIPHER_MODE_CTR) /** - * \brief Blowfish-CTR buffer encryption/decryption + * \brief Perform a Blowfish-CTR buffer encryption/decryption operation. * * \warning You must never reuse a nonce value with the same key. Doing so * would void the encryption for the two messages encrypted with @@ -215,18 +252,24 @@ int mbedtls_blowfish_crypt_cfb64( mbedtls_blowfish_context *ctx, * content must not be written to insecure storage and should be * securely discarded as soon as it's no longer needed. * - * \param ctx Blowfish context - * \param length The length of the data + * \param ctx The Blowfish context to use. This must be initialized + * and bound to a key. + * \param length The length of the input data in Bytes. * \param nc_off The offset in the current stream_block (for resuming - * within current cipher stream). The offset pointer to - * should be 0 at the start of a stream. - * \param nonce_counter The 64-bit nonce and counter. - * \param stream_block The saved stream-block for resuming. Is overwritten - * by the function. - * \param input The input data stream - * \param output The output data stream - * - * \return 0 if successful + * within current cipher stream). The offset pointer + * should be \c 0 at the start of a stream and must be + * smaller than \c 8. It is updated by this function. + * \param nonce_counter The 64-bit nonce and counter. This must point to a + * read/write buffer of length \c 8 Bytes. + * \param stream_block The saved stream-block for resuming. This must point to + * a read/write buffer of length \c 8 Bytes. + * \param input The input data. This must be a readable buffer of + * length \p length Bytes. + * \param output The output data. This must be a writable buffer of + * length \p length Bytes. + * + * \return \c 0 if successful. + * \return A negative error code on failure. */ int mbedtls_blowfish_crypt_ctr( mbedtls_blowfish_context *ctx, size_t length, diff --git a/thirdparty/mbedtls/include/mbedtls/bn_mul.h b/thirdparty/mbedtls/include/mbedtls/bn_mul.h index b587317d95..2f7b72fe4c 100644 --- a/thirdparty/mbedtls/include/mbedtls/bn_mul.h +++ b/thirdparty/mbedtls/include/mbedtls/bn_mul.h @@ -170,19 +170,19 @@ #define MULADDC_INIT \ asm( \ - "xorq %%r8, %%r8 \n\t" + "xorq %%r8, %%r8\n" #define MULADDC_CORE \ - "movq (%%rsi), %%rax \n\t" \ - "mulq %%rbx \n\t" \ - "addq $8, %%rsi \n\t" \ - "addq %%rcx, %%rax \n\t" \ - "movq %%r8, %%rcx \n\t" \ - "adcq $0, %%rdx \n\t" \ - "nop \n\t" \ - "addq %%rax, (%%rdi) \n\t" \ - "adcq %%rdx, %%rcx \n\t" \ - "addq $8, %%rdi \n\t" + "movq (%%rsi), %%rax\n" \ + "mulq %%rbx\n" \ + "addq $8, %%rsi\n" \ + "addq %%rcx, %%rax\n" \ + "movq %%r8, %%rcx\n" \ + "adcq $0, %%rdx\n" \ + "nop \n" \ + "addq %%rax, (%%rdi)\n" \ + "adcq %%rdx, %%rcx\n" \ + "addq $8, %%rdi\n" #define MULADDC_STOP \ : "+c" (c), "+D" (d), "+S" (s) \ @@ -565,9 +565,8 @@ #endif /* TriCore */ /* - * gcc -O0 by default uses r7 for the frame pointer, so it complains about our - * use of r7 below, unless -fomit-frame-pointer is passed. Unfortunately, - * passing that option is not easy when building with yotta. + * Note, gcc -O0 by default uses r7 for the frame pointer, so it complains about + * our use of r7 below, unless -fomit-frame-pointer is passed. * * On the other hand, -fomit-frame-pointer is implied by any -Ox options with * x !=0, which we can detect using __OPTIMIZE__ (which is also defined by @@ -637,6 +636,23 @@ "r6", "r7", "r8", "r9", "cc" \ ); +#elif defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1) + +#define MULADDC_INIT \ + asm( + +#define MULADDC_CORE \ + "ldr r0, [%0], #4 \n\t" \ + "ldr r1, [%1] \n\t" \ + "umaal r1, %2, %3, r0 \n\t" \ + "str r1, [%1], #4 \n\t" + +#define MULADDC_STOP \ + : "=r" (s), "=r" (d), "=r" (c) \ + : "r" (b), "0" (s), "1" (d), "2" (c) \ + : "r0", "r1", "memory" \ + ); + #else #define MULADDC_INIT \ diff --git a/thirdparty/mbedtls/include/mbedtls/camellia.h b/thirdparty/mbedtls/include/mbedtls/camellia.h index 7e4721af78..0f7c42c92d 100644 --- a/thirdparty/mbedtls/include/mbedtls/camellia.h +++ b/thirdparty/mbedtls/include/mbedtls/camellia.h @@ -33,11 +33,20 @@ #include <stddef.h> #include <stdint.h> +#include "platform_util.h" + #define MBEDTLS_CAMELLIA_ENCRYPT 1 #define MBEDTLS_CAMELLIA_DECRYPT 0 -#define MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH -0x0024 /**< Invalid key length. */ -#define MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH -0x0026 /**< Invalid data input length. */ +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#define MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH MBEDTLS_DEPRECATED_NUMERIC_CONSTANT( -0x0024 ) +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ +#define MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA -0x0024 /**< Bad input data. */ + +#define MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH -0x0026 /**< Invalid data input length. */ + +/* MBEDTLS_ERR_CAMELLIA_HW_ACCEL_FAILED is deprecated and should not be used. + */ #define MBEDTLS_ERR_CAMELLIA_HW_ACCEL_FAILED -0x0027 /**< Camellia hardware accelerator failed. */ #ifdef __cplusplus @@ -51,7 +60,7 @@ extern "C" { /** * \brief CAMELLIA context structure */ -typedef struct +typedef struct mbedtls_camellia_context { int nr; /*!< number of rounds */ uint32_t rk[68]; /*!< CAMELLIA round keys */ @@ -63,52 +72,68 @@ mbedtls_camellia_context; #endif /* MBEDTLS_CAMELLIA_ALT */ /** - * \brief Initialize CAMELLIA context + * \brief Initialize a CAMELLIA context. * - * \param ctx CAMELLIA context to be initialized + * \param ctx The CAMELLIA context to be initialized. + * This must not be \c NULL. */ void mbedtls_camellia_init( mbedtls_camellia_context *ctx ); /** - * \brief Clear CAMELLIA context + * \brief Clear a CAMELLIA context. * - * \param ctx CAMELLIA context to be cleared + * \param ctx The CAMELLIA context to be cleared. This may be \c NULL, + * in which case this function returns immediately. If it is not + * \c NULL, it must be initialized. */ void mbedtls_camellia_free( mbedtls_camellia_context *ctx ); /** - * \brief CAMELLIA key schedule (encryption) + * \brief Perform a CAMELLIA key schedule operation for encryption. * - * \param ctx CAMELLIA context to be initialized - * \param key encryption key - * \param keybits must be 128, 192 or 256 + * \param ctx The CAMELLIA context to use. This must be initialized. + * \param key The encryption key to use. This must be a readable buffer + * of size \p keybits Bits. + * \param keybits The length of \p key in Bits. This must be either \c 128, + * \c 192 or \c 256. * - * \return 0 if successful, or MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH + * \return \c 0 if successful. + * \return A negative error code on failure. */ -int mbedtls_camellia_setkey_enc( mbedtls_camellia_context *ctx, const unsigned char *key, - unsigned int keybits ); +int mbedtls_camellia_setkey_enc( mbedtls_camellia_context *ctx, + const unsigned char *key, + unsigned int keybits ); /** - * \brief CAMELLIA key schedule (decryption) + * \brief Perform a CAMELLIA key schedule operation for decryption. * - * \param ctx CAMELLIA context to be initialized - * \param key decryption key - * \param keybits must be 128, 192 or 256 + * \param ctx The CAMELLIA context to use. This must be initialized. + * \param key The decryption key. This must be a readable buffer + * of size \p keybits Bits. + * \param keybits The length of \p key in Bits. This must be either \c 128, + * \c 192 or \c 256. * - * \return 0 if successful, or MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH + * \return \c 0 if successful. + * \return A negative error code on failure. */ -int mbedtls_camellia_setkey_dec( mbedtls_camellia_context *ctx, const unsigned char *key, - unsigned int keybits ); +int mbedtls_camellia_setkey_dec( mbedtls_camellia_context *ctx, + const unsigned char *key, + unsigned int keybits ); /** - * \brief CAMELLIA-ECB block encryption/decryption - * - * \param ctx CAMELLIA context - * \param mode MBEDTLS_CAMELLIA_ENCRYPT or MBEDTLS_CAMELLIA_DECRYPT - * \param input 16-byte input block - * \param output 16-byte output block - * - * \return 0 if successful + * \brief Perform a CAMELLIA-ECB block encryption/decryption operation. + * + * \param ctx The CAMELLIA context to use. This must be initialized + * and bound to a key. + * \param mode The mode of operation. This must be either + * #MBEDTLS_CAMELLIA_ENCRYPT or #MBEDTLS_CAMELLIA_DECRYPT. + * \param input The input block. This must be a readable buffer + * of size \c 16 Bytes. + * \param output The output block. This must be a writable buffer + * of size \c 16 Bytes. + * + * \return \c 0 if successful. + * \return A negative error code on failure. */ int mbedtls_camellia_crypt_ecb( mbedtls_camellia_context *ctx, int mode, @@ -117,9 +142,7 @@ int mbedtls_camellia_crypt_ecb( mbedtls_camellia_context *ctx, #if defined(MBEDTLS_CIPHER_MODE_CBC) /** - * \brief CAMELLIA-CBC buffer encryption/decryption - * Length should be a multiple of the block - * size (16 bytes) + * \brief Perform a CAMELLIA-CBC buffer encryption/decryption operation. * * \note Upon exit, the content of the IV is updated so that you can * call the function same function again on the following @@ -129,15 +152,22 @@ int mbedtls_camellia_crypt_ecb( mbedtls_camellia_context *ctx, * IV, you should either save it manually or use the cipher * module instead. * - * \param ctx CAMELLIA context - * \param mode MBEDTLS_CAMELLIA_ENCRYPT or MBEDTLS_CAMELLIA_DECRYPT - * \param length length of the input data - * \param iv initialization vector (updated after use) - * \param input buffer holding the input data - * \param output buffer holding the output data - * - * \return 0 if successful, or - * MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH + * \param ctx The CAMELLIA context to use. This must be initialized + * and bound to a key. + * \param mode The mode of operation. This must be either + * #MBEDTLS_CAMELLIA_ENCRYPT or #MBEDTLS_CAMELLIA_DECRYPT. + * \param length The length in Bytes of the input data \p input. + * This must be a multiple of \c 16 Bytes. + * \param iv The initialization vector. This must be a read/write buffer + * of length \c 16 Bytes. It is updated to allow streaming + * use as explained above. + * \param input The buffer holding the input data. This must point to a + * readable buffer of length \p length Bytes. + * \param output The buffer holding the output data. This must point to a + * writable buffer of length \p length Bytes. + * + * \return \c 0 if successful. + * \return A negative error code on failure. */ int mbedtls_camellia_crypt_cbc( mbedtls_camellia_context *ctx, int mode, @@ -149,11 +179,14 @@ int mbedtls_camellia_crypt_cbc( mbedtls_camellia_context *ctx, #if defined(MBEDTLS_CIPHER_MODE_CFB) /** - * \brief CAMELLIA-CFB128 buffer encryption/decryption + * \brief Perform a CAMELLIA-CFB128 buffer encryption/decryption + * operation. * - * Note: Due to the nature of CFB you should use the same key schedule for - * both encryption and decryption. So a context initialized with - * mbedtls_camellia_setkey_enc() for both MBEDTLS_CAMELLIA_ENCRYPT and CAMELLIE_DECRYPT. + * \note Due to the nature of CFB mode, you should use the same + * key for both encryption and decryption. In particular, calls + * to this function should be preceded by a key-schedule via + * mbedtls_camellia_setkey_enc() regardless of whether \p mode + * is #MBEDTLS_CAMELLIA_ENCRYPT or #MBEDTLS_CAMELLIA_DECRYPT. * * \note Upon exit, the content of the IV is updated so that you can * call the function same function again on the following @@ -163,16 +196,24 @@ int mbedtls_camellia_crypt_cbc( mbedtls_camellia_context *ctx, * IV, you should either save it manually or use the cipher * module instead. * - * \param ctx CAMELLIA context - * \param mode MBEDTLS_CAMELLIA_ENCRYPT or MBEDTLS_CAMELLIA_DECRYPT - * \param length length of the input data - * \param iv_off offset in IV (updated after use) - * \param iv initialization vector (updated after use) - * \param input buffer holding the input data - * \param output buffer holding the output data - * - * \return 0 if successful, or - * MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH + * \param ctx The CAMELLIA context to use. This must be initialized + * and bound to a key. + * \param mode The mode of operation. This must be either + * #MBEDTLS_CAMELLIA_ENCRYPT or #MBEDTLS_CAMELLIA_DECRYPT. + * \param length The length of the input data \p input. Any value is allowed. + * \param iv_off The current offset in the IV. This must be smaller + * than \c 16 Bytes. It is updated after this call to allow + * the aforementioned streaming usage. + * \param iv The initialization vector. This must be a read/write buffer + * of length \c 16 Bytes. It is updated after this call to + * allow the aforementioned streaming usage. + * \param input The buffer holding the input data. This must be a readable + * buffer of size \p length Bytes. + * \param output The buffer to hold the output data. This must be a writable + * buffer of length \p length Bytes. + * + * \return \c 0 if successful. + * \return A negative error code on failure. */ int mbedtls_camellia_crypt_cfb128( mbedtls_camellia_context *ctx, int mode, @@ -185,11 +226,13 @@ int mbedtls_camellia_crypt_cfb128( mbedtls_camellia_context *ctx, #if defined(MBEDTLS_CIPHER_MODE_CTR) /** - * \brief CAMELLIA-CTR buffer encryption/decryption + * \brief Perform a CAMELLIA-CTR buffer encryption/decryption operation. * - * Note: Due to the nature of CTR you should use the same key schedule for - * both encryption and decryption. So a context initialized with - * mbedtls_camellia_setkey_enc() for both MBEDTLS_CAMELLIA_ENCRYPT and MBEDTLS_CAMELLIA_DECRYPT. + * *note Due to the nature of CTR mode, you should use the same + * key for both encryption and decryption. In particular, calls + * to this function should be preceded by a key-schedule via + * mbedtls_camellia_setkey_enc() regardless of whether \p mode + * is #MBEDTLS_CAMELLIA_ENCRYPT or #MBEDTLS_CAMELLIA_DECRYPT. * * \warning You must never reuse a nonce value with the same key. Doing so * would void the encryption for the two messages encrypted with @@ -212,41 +255,49 @@ int mbedtls_camellia_crypt_cfb128( mbedtls_camellia_context *ctx, * per-message nonce, handled by yourself, and the second one * updated by this function internally. * - * For example, you might reserve the first 12 bytes for the - * per-message nonce, and the last 4 bytes for internal use. In that - * case, before calling this function on a new message you need to - * set the first 12 bytes of \p nonce_counter to your chosen nonce - * value, the last 4 to 0, and \p nc_off to 0 (which will cause \p - * stream_block to be ignored). That way, you can encrypt at most - * 2**96 messages of up to 2**32 blocks each with the same key. + * For example, you might reserve the first \c 12 Bytes for the + * per-message nonce, and the last \c 4 Bytes for internal use. + * In that case, before calling this function on a new message you + * need to set the first \c 12 Bytes of \p nonce_counter to your + * chosen nonce value, the last four to \c 0, and \p nc_off to \c 0 + * (which will cause \p stream_block to be ignored). That way, you + * can encrypt at most \c 2**96 messages of up to \c 2**32 blocks + * each with the same key. * * The per-message nonce (or information sufficient to reconstruct - * it) needs to be communicated with the ciphertext and must be unique. - * The recommended way to ensure uniqueness is to use a message - * counter. An alternative is to generate random nonces, but this - * limits the number of messages that can be securely encrypted: - * for example, with 96-bit random nonces, you should not encrypt - * more than 2**32 messages with the same key. + * it) needs to be communicated with the ciphertext and must be + * unique. The recommended way to ensure uniqueness is to use a + * message counter. An alternative is to generate random nonces, + * but this limits the number of messages that can be securely + * encrypted: for example, with 96-bit random nonces, you should + * not encrypt more than 2**32 messages with the same key. * * Note that for both stategies, sizes are measured in blocks and - * that a CAMELLIA block is 16 bytes. + * that a CAMELLIA block is \c 16 Bytes. * * \warning Upon return, \p stream_block contains sensitive data. Its * content must not be written to insecure storage and should be * securely discarded as soon as it's no longer needed. * - * \param ctx CAMELLIA context - * \param length The length of the data - * \param nc_off The offset in the current stream_block (for resuming + * \param ctx The CAMELLIA context to use. This must be initialized + * and bound to a key. + * \param length The length of the input data \p input in Bytes. + * Any value is allowed. + * \param nc_off The offset in the current \p stream_block (for resuming * within current cipher stream). The offset pointer to - * should be 0 at the start of a stream. - * \param nonce_counter The 128-bit nonce and counter. - * \param stream_block The saved stream-block for resuming. Is overwritten - * by the function. - * \param input The input data stream - * \param output The output data stream - * - * \return 0 if successful + * should be \c 0 at the start of a stream. It is updated + * at the end of this call. + * \param nonce_counter The 128-bit nonce and counter. This must be a read/write + * buffer of length \c 16 Bytes. + * \param stream_block The saved stream-block for resuming. This must be a + * read/write buffer of length \c 16 Bytes. + * \param input The input data stream. This must be a readable buffer of + * size \p length Bytes. + * \param output The output data stream. This must be a writable buffer + * of size \p length Bytes. + * + * \return \c 0 if successful. + * \return A negative error code on failure. */ int mbedtls_camellia_crypt_ctr( mbedtls_camellia_context *ctx, size_t length, diff --git a/thirdparty/mbedtls/include/mbedtls/ccm.h b/thirdparty/mbedtls/include/mbedtls/ccm.h index 5d727e7cca..3f6b8f6709 100644 --- a/thirdparty/mbedtls/include/mbedtls/ccm.h +++ b/thirdparty/mbedtls/include/mbedtls/ccm.h @@ -53,8 +53,9 @@ #define MBEDTLS_ERR_CCM_BAD_INPUT -0x000D /**< Bad input parameters to the function. */ #define MBEDTLS_ERR_CCM_AUTH_FAILED -0x000F /**< Authenticated decryption failed. */ -#define MBEDTLS_ERR_CCM_HW_ACCEL_FAILED -0x0011 /**< CCM hardware accelerator failed. */ +/* MBEDTLS_ERR_CCM_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_CCM_HW_ACCEL_FAILED -0x0011 /**< CCM hardware accelerator failed. */ #ifdef __cplusplus extern "C" { @@ -68,7 +69,8 @@ extern "C" { * \brief The CCM context-type definition. The CCM context is passed * to the APIs called. */ -typedef struct { +typedef struct mbedtls_ccm_context +{ mbedtls_cipher_context_t cipher_ctx; /*!< The cipher context used. */ } mbedtls_ccm_context; @@ -82,7 +84,7 @@ mbedtls_ccm_context; * to make references valid, and prepare the context * for mbedtls_ccm_setkey() or mbedtls_ccm_free(). * - * \param ctx The CCM context to initialize. + * \param ctx The CCM context to initialize. This must not be \c NULL. */ void mbedtls_ccm_init( mbedtls_ccm_context *ctx ); @@ -90,9 +92,10 @@ void mbedtls_ccm_init( mbedtls_ccm_context *ctx ); * \brief This function initializes the CCM context set in the * \p ctx parameter and sets the encryption key. * - * \param ctx The CCM context to initialize. + * \param ctx The CCM context to initialize. This must be an initialized + * context. * \param cipher The 128-bit block cipher to use. - * \param key The encryption key. + * \param key The encryption key. This must not be \c NULL. * \param keybits The key size in bits. This must be acceptable by the cipher. * * \return \c 0 on success. @@ -107,7 +110,8 @@ int mbedtls_ccm_setkey( mbedtls_ccm_context *ctx, * \brief This function releases and clears the specified CCM context * and underlying cipher sub-context. * - * \param ctx The CCM context to clear. + * \param ctx The CCM context to clear. If this is \c NULL, the function + * has no effect. Otherwise, this must be initialized. */ void mbedtls_ccm_free( mbedtls_ccm_context *ctx ); @@ -120,19 +124,27 @@ void mbedtls_ccm_free( mbedtls_ccm_context *ctx ); * \p tag = \p output + \p length, and make sure that the * output buffer is at least \p length + \p tag_len wide. * - * \param ctx The CCM context to use for encryption. + * \param ctx The CCM context to use for encryption. This must be + * initialized and bound to a key. * \param length The length of the input data in Bytes. - * \param iv Initialization vector (nonce). + * \param iv The initialization vector (nonce). This must be a readable + * buffer of at least \p iv_len Bytes. * \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12, * or 13. The length L of the message length field is * 15 - \p iv_len. - * \param add The additional data field. + * \param add The additional data field. If \p add_len is greater than + * zero, \p add must be a readable buffer of at least that + * length. * \param add_len The length of additional data in Bytes. - * Must be less than 2^16 - 2^8. - * \param input The buffer holding the input data. - * \param output The buffer holding the output data. - * Must be at least \p length Bytes wide. - * \param tag The buffer holding the authentication field. + * This must be less than `2^16 - 2^8`. + * \param input The buffer holding the input data. If \p length is greater + * than zero, \p input must be a readable buffer of at least + * that length. + * \param output The buffer holding the output data. If \p length is greater + * than zero, \p output must be a writable buffer of at least + * that length. + * \param tag The buffer holding the authentication field. This must be a + * readable buffer of at least \p tag_len Bytes. * \param tag_len The length of the authentication field to generate in Bytes: * 4, 6, 8, 10, 12, 14 or 16. * @@ -158,23 +170,30 @@ int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length, * the tag length has to be encoded into the \p iv passed to * this function. * - * \param ctx The CCM context to use for encryption. + * \param ctx The CCM context to use for encryption. This must be + * initialized and bound to a key. * \param length The length of the input data in Bytes. - * \param iv Initialization vector (nonce). + * \param iv The initialization vector (nonce). This must be a readable + * buffer of at least \p iv_len Bytes. * \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12, * or 13. The length L of the message length field is * 15 - \p iv_len. - * \param add The additional data field. + * \param add The additional data field. This must be a readable buffer of + * at least \p add_len Bytes. * \param add_len The length of additional data in Bytes. - * Must be less than 2^16 - 2^8. - * \param input The buffer holding the input data. - * \param output The buffer holding the output data. - * Must be at least \p length Bytes wide. - * \param tag The buffer holding the authentication field. + * This must be less than 2^16 - 2^8. + * \param input The buffer holding the input data. If \p length is greater + * than zero, \p input must be a readable buffer of at least + * that length. + * \param output The buffer holding the output data. If \p length is greater + * than zero, \p output must be a writable buffer of at least + * that length. + * \param tag The buffer holding the authentication field. This must be a + * readable buffer of at least \p tag_len Bytes. * \param tag_len The length of the authentication field to generate in Bytes: * 0, 4, 6, 8, 10, 12, 14 or 16. * - * \warning Passing 0 as \p tag_len means that the message is no + * \warning Passing \c 0 as \p tag_len means that the message is no * longer authenticated. * * \return \c 0 on success. @@ -190,20 +209,27 @@ int mbedtls_ccm_star_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length, * \brief This function performs a CCM authenticated decryption of a * buffer. * - * \param ctx The CCM context to use for decryption. + * \param ctx The CCM context to use for decryption. This must be + * initialized and bound to a key. * \param length The length of the input data in Bytes. - * \param iv Initialization vector (nonce). + * \param iv The initialization vector (nonce). This must be a readable + * buffer of at least \p iv_len Bytes. * \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12, * or 13. The length L of the message length field is * 15 - \p iv_len. - * \param add The additional data field. + * \param add The additional data field. This must be a readable buffer + * of at least that \p add_len Bytes.. * \param add_len The length of additional data in Bytes. - * Must be less than 2^16 - 2^8. - * \param input The buffer holding the input data. - * \param output The buffer holding the output data. - * Must be at least \p length Bytes wide. - * \param tag The buffer holding the authentication field. - * \param tag_len The length of the authentication field in Bytes. + * This must be less than 2^16 - 2^8. + * \param input The buffer holding the input data. If \p length is greater + * than zero, \p input must be a readable buffer of at least + * that length. + * \param output The buffer holding the output data. If \p length is greater + * than zero, \p output must be a writable buffer of at least + * that length. + * \param tag The buffer holding the authentication field. This must be a + * readable buffer of at least \p tag_len Bytes. + * \param tag_len The length of the authentication field to generate in Bytes: * 4, 6, 8, 10, 12, 14 or 16. * * \return \c 0 on success. This indicates that the message is authentic. @@ -225,23 +251,30 @@ int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length, * this function as \p tag_len. (\p tag needs to be adjusted * accordingly.) * - * \param ctx The CCM context to use for decryption. + * \param ctx The CCM context to use for decryption. This must be + * initialized and bound to a key. * \param length The length of the input data in Bytes. - * \param iv Initialization vector (nonce). + * \param iv The initialization vector (nonce). This must be a readable + * buffer of at least \p iv_len Bytes. * \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12, * or 13. The length L of the message length field is * 15 - \p iv_len. - * \param add The additional data field. + * \param add The additional data field. This must be a readable buffer of + * at least that \p add_len Bytes. * \param add_len The length of additional data in Bytes. - * Must be less than 2^16 - 2^8. - * \param input The buffer holding the input data. - * \param output The buffer holding the output data. - * Must be at least \p length Bytes wide. - * \param tag The buffer holding the authentication field. + * This must be less than 2^16 - 2^8. + * \param input The buffer holding the input data. If \p length is greater + * than zero, \p input must be a readable buffer of at least + * that length. + * \param output The buffer holding the output data. If \p length is greater + * than zero, \p output must be a writable buffer of at least + * that length. + * \param tag The buffer holding the authentication field. This must be a + * readable buffer of at least \p tag_len Bytes. * \param tag_len The length of the authentication field in Bytes. * 0, 4, 6, 8, 10, 12, 14 or 16. * - * \warning Passing 0 as \p tag_len means that the message is no + * \warning Passing \c 0 as \p tag_len means that the message is nos * longer authenticated. * * \return \c 0 on success. diff --git a/thirdparty/mbedtls/include/mbedtls/chacha20.h b/thirdparty/mbedtls/include/mbedtls/chacha20.h index 47bd7d38b9..2ae5e6e5f4 100644 --- a/thirdparty/mbedtls/include/mbedtls/chacha20.h +++ b/thirdparty/mbedtls/include/mbedtls/chacha20.h @@ -43,7 +43,13 @@ #include <stddef.h> #define MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA -0x0051 /**< Invalid input parameter(s). */ + +/* MBEDTLS_ERR_CHACHA20_FEATURE_UNAVAILABLE is deprecated and should not be + * used. */ #define MBEDTLS_ERR_CHACHA20_FEATURE_UNAVAILABLE -0x0053 /**< Feature not available. For example, s part of the API is not implemented. */ + +/* MBEDTLS_ERR_CHACHA20_HW_ACCEL_FAILED is deprecated and should not be used. + */ #define MBEDTLS_ERR_CHACHA20_HW_ACCEL_FAILED -0x0055 /**< Chacha20 hardware accelerator failed. */ #ifdef __cplusplus @@ -52,7 +58,7 @@ extern "C" { #if !defined(MBEDTLS_CHACHA20_ALT) -typedef struct +typedef struct mbedtls_chacha20_context { uint32_t state[16]; /*! The state (before round operations). */ uint8_t keystream8[64]; /*! Leftover keystream bytes. */ @@ -77,13 +83,18 @@ mbedtls_chacha20_context; * \c mbedtls_chacha20_free(). * * \param ctx The ChaCha20 context to initialize. + * This must not be \c NULL. */ void mbedtls_chacha20_init( mbedtls_chacha20_context *ctx ); /** - * \brief This function releases and clears the specified ChaCha20 context. + * \brief This function releases and clears the specified + * ChaCha20 context. + * + * \param ctx The ChaCha20 context to clear. This may be \c NULL, + * in which case this function is a no-op. If it is not + * \c NULL, it must point to an initialized context. * - * \param ctx The ChaCha20 context to clear. */ void mbedtls_chacha20_free( mbedtls_chacha20_context *ctx ); @@ -96,7 +107,9 @@ void mbedtls_chacha20_free( mbedtls_chacha20_context *ctx ); * \c mbedtls_chacha_update(). * * \param ctx The ChaCha20 context to which the key should be bound. - * \param key The encryption/decryption key. Must be 32 bytes in length. + * It must be initialized. + * \param key The encryption/decryption key. This must be \c 32 Bytes + * in length. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA if ctx or key is NULL. @@ -115,8 +128,9 @@ int mbedtls_chacha20_setkey( mbedtls_chacha20_context *ctx, * messages encrypted with the same nonce and key. * * \param ctx The ChaCha20 context to which the nonce should be bound. - * \param nonce The nonce. Must be 12 bytes in size. - * \param counter The initial counter value. This is usually 0. + * It must be initialized and bound to a key. + * \param nonce The nonce. This must be \c 12 Bytes in size. + * \param counter The initial counter value. This is usually \c 0. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA if ctx or nonce is @@ -144,16 +158,16 @@ int mbedtls_chacha20_starts( mbedtls_chacha20_context* ctx, * key and nonce. * * \param ctx The ChaCha20 context to use for encryption or decryption. - * \param size The length of the input data in bytes. + * It must be initialized and bound to a key and nonce. + * \param size The length of the input data in Bytes. * \param input The buffer holding the input data. - * This pointer can be NULL if size == 0. + * This pointer can be \c NULL if `size == 0`. * \param output The buffer holding the output data. - * Must be able to hold \p size bytes. - * This pointer can be NULL if size == 0. + * This must be able to hold \p size Bytes. + * This pointer can be \c NULL if `size == 0`. * * \return \c 0 on success. - * \return #MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA if the ctx, input, or - * output pointers are NULL. + * \return A negative error code on failure. */ int mbedtls_chacha20_update( mbedtls_chacha20_context *ctx, size_t size, @@ -174,19 +188,19 @@ int mbedtls_chacha20_update( mbedtls_chacha20_context *ctx, * \note The \p input and \p output pointers must either be equal or * point to non-overlapping buffers. * - * \param key The encryption/decryption key. Must be 32 bytes in length. - * \param nonce The nonce. Must be 12 bytes in size. - * \param counter The initial counter value. This is usually 0. - * \param size The length of the input data in bytes. + * \param key The encryption/decryption key. + * This must be \c 32 Bytes in length. + * \param nonce The nonce. This must be \c 12 Bytes in size. + * \param counter The initial counter value. This is usually \c 0. + * \param size The length of the input data in Bytes. * \param input The buffer holding the input data. - * This pointer can be NULL if size == 0. + * This pointer can be \c NULL if `size == 0`. * \param output The buffer holding the output data. - * Must be able to hold \p size bytes. - * This pointer can be NULL if size == 0. + * This must be able to hold \p size Bytes. + * This pointer can be \c NULL if `size == 0`. * * \return \c 0 on success. - * \return #MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA if key, nonce, input, - * or output is NULL. + * \return A negative error code on failure. */ int mbedtls_chacha20_crypt( const unsigned char key[32], const unsigned char nonce[12], diff --git a/thirdparty/mbedtls/include/mbedtls/chachapoly.h b/thirdparty/mbedtls/include/mbedtls/chachapoly.h index 42b2b230c5..49e615d278 100644 --- a/thirdparty/mbedtls/include/mbedtls/chachapoly.h +++ b/thirdparty/mbedtls/include/mbedtls/chachapoly.h @@ -60,7 +60,7 @@ mbedtls_chachapoly_mode_t; #include "chacha20.h" -typedef struct +typedef struct mbedtls_chachapoly_context { mbedtls_chacha20_context chacha20_ctx; /**< The ChaCha20 context. */ mbedtls_poly1305_context poly1305_ctx; /**< The Poly1305 context. */ @@ -115,27 +115,29 @@ mbedtls_chachapoly_context; * all previous outputs of \c mbedtls_chachapoly_update(), * otherwise you can now safely use the plaintext. * - * \param ctx The ChachaPoly context to initialize. + * \param ctx The ChachaPoly context to initialize. Must not be \c NULL. */ void mbedtls_chachapoly_init( mbedtls_chachapoly_context *ctx ); /** - * \brief This function releases and clears the specified ChaCha20-Poly1305 context. + * \brief This function releases and clears the specified + * ChaCha20-Poly1305 context. * - * \param ctx The ChachaPoly context to clear. + * \param ctx The ChachaPoly context to clear. This may be \c NULL, in which + * case this function is a no-op. */ void mbedtls_chachapoly_free( mbedtls_chachapoly_context *ctx ); /** - * \brief This function sets the ChaCha20-Poly1305 symmetric encryption key. + * \brief This function sets the ChaCha20-Poly1305 + * symmetric encryption key. * * \param ctx The ChaCha20-Poly1305 context to which the key should be - * bound. - * \param key The 256-bit (32 bytes) key. + * bound. This must be initialized. + * \param key The \c 256 Bit (\c 32 Bytes) key. * * \return \c 0 on success. - * \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA - * if \p ctx or \p key are NULL. + * \return A negative error code on failure. */ int mbedtls_chachapoly_setkey( mbedtls_chachapoly_context *ctx, const unsigned char key[32] ); @@ -155,14 +157,15 @@ int mbedtls_chachapoly_setkey( mbedtls_chachapoly_context *ctx, * \warning Decryption with the piecewise API is discouraged, see the * warning on \c mbedtls_chachapoly_init(). * - * \param ctx The ChaCha20-Poly1305 context. - * \param nonce The nonce/IV to use for the message. Must be 12 bytes. + * \param ctx The ChaCha20-Poly1305 context. This must be initialized + * and bound to a key. + * \param nonce The nonce/IV to use for the message. + * This must be a redable buffer of length \c 12 Bytes. * \param mode The operation to perform: #MBEDTLS_CHACHAPOLY_ENCRYPT or * #MBEDTLS_CHACHAPOLY_DECRYPT (discouraged, see warning). * * \return \c 0 on success. - * \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA - * if \p ctx or \p mac are NULL. + * \return A negative error code on failure. */ int mbedtls_chachapoly_starts( mbedtls_chachapoly_context *ctx, const unsigned char nonce[12], @@ -193,11 +196,12 @@ int mbedtls_chachapoly_starts( mbedtls_chachapoly_context *ctx, * \warning Decryption with the piecewise API is discouraged, see the * warning on \c mbedtls_chachapoly_init(). * - * \param ctx The ChaCha20-Poly1305 context to use. - * \param aad_len The length (in bytes) of the AAD. The length has no + * \param ctx The ChaCha20-Poly1305 context. This must be initialized + * and bound to a key. + * \param aad_len The length in Bytes of the AAD. The length has no * restrictions. * \param aad Buffer containing the AAD. - * This pointer can be NULL if aad_len == 0. + * This pointer can be \c NULL if `aad_len == 0`. * * \return \c 0 on success. * \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA @@ -227,20 +231,19 @@ int mbedtls_chachapoly_update_aad( mbedtls_chachapoly_context *ctx, * \warning Decryption with the piecewise API is discouraged, see the * warning on \c mbedtls_chachapoly_init(). * - * \param ctx The ChaCha20-Poly1305 context to use. + * \param ctx The ChaCha20-Poly1305 context to use. This must be initialized. * \param len The length (in bytes) of the data to encrypt or decrypt. * \param input The buffer containing the data to encrypt or decrypt. - * This pointer can be NULL if len == 0. - * \param output The buffer to where the encrypted or decrypted data is written. - * Must be able to hold \p len bytes. - * This pointer can be NULL if len == 0. + * This pointer can be \c NULL if `len == 0`. + * \param output The buffer to where the encrypted or decrypted data is + * written. This must be able to hold \p len bytes. + * This pointer can be \c NULL if `len == 0`. * * \return \c 0 on success. - * \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA - * if \p ctx, \p input, or \p output are NULL. * \return #MBEDTLS_ERR_CHACHAPOLY_BAD_STATE * if the operation has not been started or has been * finished. + * \return Another negative error code on other kinds of failure. */ int mbedtls_chachapoly_update( mbedtls_chachapoly_context *ctx, size_t len, @@ -251,18 +254,17 @@ int mbedtls_chachapoly_update( mbedtls_chachapoly_context *ctx, * \brief This function finished the ChaCha20-Poly1305 operation and * generates the MAC (authentication tag). * - * \param ctx The ChaCha20-Poly1305 context to use. + * \param ctx The ChaCha20-Poly1305 context to use. This must be initialized. * \param mac The buffer to where the 128-bit (16 bytes) MAC is written. * * \warning Decryption with the piecewise API is discouraged, see the * warning on \c mbedtls_chachapoly_init(). * * \return \c 0 on success. - * \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA - * if \p ctx or \p mac are NULL. * \return #MBEDTLS_ERR_CHACHAPOLY_BAD_STATE * if the operation has not been started or has been * finished. + * \return Another negative error code on other kinds of failure. */ int mbedtls_chachapoly_finish( mbedtls_chachapoly_context *ctx, unsigned char mac[16] ); @@ -280,20 +282,21 @@ int mbedtls_chachapoly_finish( mbedtls_chachapoly_context *ctx, * and key. * * \param ctx The ChaCha20-Poly1305 context to use (holds the key). + * This must be initialized. * \param length The length (in bytes) of the data to encrypt or decrypt. * \param nonce The 96-bit (12 bytes) nonce/IV to use. - * \param aad The buffer containing the additional authenticated data (AAD). - * This pointer can be NULL if aad_len == 0. + * \param aad The buffer containing the additional authenticated + * data (AAD). This pointer can be \c NULL if `aad_len == 0`. * \param aad_len The length (in bytes) of the AAD data to process. * \param input The buffer containing the data to encrypt or decrypt. - * This pointer can be NULL if ilen == 0. - * \param output The buffer to where the encrypted or decrypted data is written. - * This pointer can be NULL if ilen == 0. - * \param tag The buffer to where the computed 128-bit (16 bytes) MAC is written. + * This pointer can be \c NULL if `ilen == 0`. + * \param output The buffer to where the encrypted or decrypted data + * is written. This pointer can be \c NULL if `ilen == 0`. + * \param tag The buffer to where the computed 128-bit (16 bytes) MAC + * is written. This must not be \c NULL. * * \return \c 0 on success. - * \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA - * if one or more of the required parameters are NULL. + * \return A negative error code on failure. */ int mbedtls_chachapoly_encrypt_and_tag( mbedtls_chachapoly_context *ctx, size_t length, @@ -312,22 +315,22 @@ int mbedtls_chachapoly_encrypt_and_tag( mbedtls_chachapoly_context *ctx, * \c mbedtls_chachapoly_setkey(). * * \param ctx The ChaCha20-Poly1305 context to use (holds the key). - * \param length The length (in bytes) of the data to decrypt. - * \param nonce The 96-bit (12 bytes) nonce/IV to use. + * \param length The length (in Bytes) of the data to decrypt. + * \param nonce The \c 96 Bit (\c 12 bytes) nonce/IV to use. * \param aad The buffer containing the additional authenticated data (AAD). - * This pointer can be NULL if aad_len == 0. + * This pointer can be \c NULL if `aad_len == 0`. * \param aad_len The length (in bytes) of the AAD data to process. * \param tag The buffer holding the authentication tag. + * This must be a readable buffer of length \c 16 Bytes. * \param input The buffer containing the data to decrypt. - * This pointer can be NULL if ilen == 0. + * This pointer can be \c NULL if `ilen == 0`. * \param output The buffer to where the decrypted data is written. - * This pointer can be NULL if ilen == 0. + * This pointer can be \c NULL if `ilen == 0`. * * \return \c 0 on success. - * \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA - * if one or more of the required parameters are NULL. * \return #MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED * if the data was not authentic. + * \return Another negative error code on other kinds of failure. */ int mbedtls_chachapoly_auth_decrypt( mbedtls_chachapoly_context *ctx, size_t length, diff --git a/thirdparty/mbedtls/include/mbedtls/check_config.h b/thirdparty/mbedtls/include/mbedtls/check_config.h index 9e6bb8a46a..b86e5807e0 100644 --- a/thirdparty/mbedtls/include/mbedtls/check_config.h +++ b/thirdparty/mbedtls/include/mbedtls/check_config.h @@ -108,6 +108,17 @@ #error "MBEDTLS_ECJPAKE_C defined, but not all prerequisites" #endif +#if defined(MBEDTLS_ECP_RESTARTABLE) && \ + ( defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT) || \ + defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT) || \ + defined(MBEDTLS_ECDSA_SIGN_ALT) || \ + defined(MBEDTLS_ECDSA_VERIFY_ALT) || \ + defined(MBEDTLS_ECDSA_GENKEY_ALT) || \ + defined(MBEDTLS_ECP_INTERNAL_ALT) || \ + defined(MBEDTLS_ECP_ALT) ) +#error "MBEDTLS_ECP_RESTARTABLE defined, but it cannot coexist with an alternative ECP implementation" +#endif + #if defined(MBEDTLS_ECDSA_DETERMINISTIC) && !defined(MBEDTLS_HMAC_DRBG_C) #error "MBEDTLS_ECDSA_DETERMINISTIC defined, but not all prerequisites" #endif @@ -127,6 +138,10 @@ #error "MBEDTLS_ECP_C defined, but not all prerequisites" #endif +#if defined(MBEDTLS_PK_PARSE_C) && !defined(MBEDTLS_ASN1_PARSE_C) +#error "MBEDTLS_PK_PARSE_C defined, but not all prerequesites" +#endif + #if defined(MBEDTLS_ENTROPY_C) && (!defined(MBEDTLS_SHA512_C) && \ !defined(MBEDTLS_SHA256_C)) #error "MBEDTLS_ENTROPY_C defined, but not all prerequisites" diff --git a/thirdparty/mbedtls/include/mbedtls/cipher.h b/thirdparty/mbedtls/include/mbedtls/cipher.h index ea0ce983f1..922b6c32c6 100644 --- a/thirdparty/mbedtls/include/mbedtls/cipher.h +++ b/thirdparty/mbedtls/include/mbedtls/cipher.h @@ -36,6 +36,7 @@ #endif #include <stddef.h> +#include "mbedtls/platform_util.h" #if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C) || defined(MBEDTLS_CHACHAPOLY_C) #define MBEDTLS_CIPHER_MODE_AEAD @@ -45,7 +46,8 @@ #define MBEDTLS_CIPHER_MODE_WITH_PADDING #endif -#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER) +#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER) || \ + defined(MBEDTLS_CHACHA20_C) #define MBEDTLS_CIPHER_MODE_STREAM #endif @@ -61,6 +63,8 @@ #define MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED -0x6280 /**< Decryption of block requires a full block. */ #define MBEDTLS_ERR_CIPHER_AUTH_FAILED -0x6300 /**< Authentication failed (for AEAD modes). */ #define MBEDTLS_ERR_CIPHER_INVALID_CONTEXT -0x6380 /**< The context is invalid. For example, because it was freed. */ + +/* MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED is deprecated and should not be used. */ #define MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED -0x6400 /**< Cipher hardware accelerator failed. */ #define MBEDTLS_CIPHER_VARIABLE_IV_LEN 0x01 /**< Cipher accepts IVs of variable length. */ @@ -235,7 +239,8 @@ typedef struct mbedtls_cmac_context_t mbedtls_cmac_context_t; * Cipher information. Allows calling cipher functions * in a generic way. */ -typedef struct { +typedef struct mbedtls_cipher_info_t +{ /** Full cipher identifier. For example, * MBEDTLS_CIPHER_AES_256_CBC. */ @@ -276,7 +281,8 @@ typedef struct { /** * Generic cipher context. */ -typedef struct { +typedef struct mbedtls_cipher_context_t +{ /** Information about the associated cipher. */ const mbedtls_cipher_info_t *cipher_info; @@ -331,11 +337,12 @@ const int *mbedtls_cipher_list( void ); * \brief This function retrieves the cipher-information * structure associated with the given cipher name. * - * \param cipher_name Name of the cipher to search for. + * \param cipher_name Name of the cipher to search for. This must not be + * \c NULL. * * \return The cipher information structure associated with the * given \p cipher_name. - * \return NULL if the associated cipher information is not found. + * \return \c NULL if the associated cipher information is not found. */ const mbedtls_cipher_info_t *mbedtls_cipher_info_from_string( const char *cipher_name ); @@ -347,7 +354,7 @@ const mbedtls_cipher_info_t *mbedtls_cipher_info_from_string( const char *cipher * * \return The cipher information structure associated with the * given \p cipher_type. - * \return NULL if the associated cipher information is not found. + * \return \c NULL if the associated cipher information is not found. */ const mbedtls_cipher_info_t *mbedtls_cipher_info_from_type( const mbedtls_cipher_type_t cipher_type ); @@ -363,7 +370,7 @@ const mbedtls_cipher_info_t *mbedtls_cipher_info_from_type( const mbedtls_cipher * * \return The cipher information structure associated with the * given \p cipher_id. - * \return NULL if the associated cipher information is not found. + * \return \c NULL if the associated cipher information is not found. */ const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values( const mbedtls_cipher_id_t cipher_id, int key_bitlen, @@ -371,6 +378,8 @@ const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values( const mbedtls_ciph /** * \brief This function initializes a \p cipher_context as NONE. + * + * \param ctx The context to be initialized. This must not be \c NULL. */ void mbedtls_cipher_init( mbedtls_cipher_context_t *ctx ); @@ -378,6 +387,10 @@ void mbedtls_cipher_init( mbedtls_cipher_context_t *ctx ); * \brief This function frees and clears the cipher-specific * context of \p ctx. Freeing \p ctx itself remains the * responsibility of the caller. + * + * \param ctx The context to be freed. If this is \c NULL, the + * function has no effect, otherwise this must point to an + * initialized context. */ void mbedtls_cipher_free( mbedtls_cipher_context_t *ctx ); @@ -387,7 +400,7 @@ void mbedtls_cipher_free( mbedtls_cipher_context_t *ctx ); * structure with the appropriate values. It also clears * the structure. * - * \param ctx The context to initialize. May not be NULL. + * \param ctx The context to initialize. This must be initialized. * \param cipher_info The cipher to use. * * \return \c 0 on success. @@ -400,19 +413,22 @@ void mbedtls_cipher_free( mbedtls_cipher_context_t *ctx ); * In future versions, the caller will be required to call * mbedtls_cipher_init() on the structure first. */ -int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx, const mbedtls_cipher_info_t *cipher_info ); +int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx, + const mbedtls_cipher_info_t *cipher_info ); /** * \brief This function returns the block size of the given cipher. * - * \param ctx The context of the cipher. Must be initialized. + * \param ctx The context of the cipher. This must be initialized. * - * \return The size of the blocks of the cipher. - * \return 0 if \p ctx has not been initialized. + * \return The block size of the underlying cipher. + * \return \c 0 if \p ctx has not been initialized. */ -static inline unsigned int mbedtls_cipher_get_block_size( const mbedtls_cipher_context_t *ctx ) +static inline unsigned int mbedtls_cipher_get_block_size( + const mbedtls_cipher_context_t *ctx ) { - if( NULL == ctx || NULL == ctx->cipher_info ) + MBEDTLS_INTERNAL_VALIDATE_RET( ctx != NULL, 0 ); + if( ctx->cipher_info == NULL ) return 0; return ctx->cipher_info->block_size; @@ -422,14 +438,16 @@ static inline unsigned int mbedtls_cipher_get_block_size( const mbedtls_cipher_c * \brief This function returns the mode of operation for * the cipher. For example, MBEDTLS_MODE_CBC. * - * \param ctx The context of the cipher. Must be initialized. + * \param ctx The context of the cipher. This must be initialized. * * \return The mode of operation. * \return #MBEDTLS_MODE_NONE if \p ctx has not been initialized. */ -static inline mbedtls_cipher_mode_t mbedtls_cipher_get_cipher_mode( const mbedtls_cipher_context_t *ctx ) +static inline mbedtls_cipher_mode_t mbedtls_cipher_get_cipher_mode( + const mbedtls_cipher_context_t *ctx ) { - if( NULL == ctx || NULL == ctx->cipher_info ) + MBEDTLS_INTERNAL_VALIDATE_RET( ctx != NULL, MBEDTLS_MODE_NONE ); + if( ctx->cipher_info == NULL ) return MBEDTLS_MODE_NONE; return ctx->cipher_info->mode; @@ -439,15 +457,17 @@ static inline mbedtls_cipher_mode_t mbedtls_cipher_get_cipher_mode( const mbedtl * \brief This function returns the size of the IV or nonce * of the cipher, in Bytes. * - * \param ctx The context of the cipher. Must be initialized. + * \param ctx The context of the cipher. This must be initialized. * * \return The recommended IV size if no IV has been set. * \return \c 0 for ciphers not using an IV or a nonce. * \return The actual size if an IV has been set. */ -static inline int mbedtls_cipher_get_iv_size( const mbedtls_cipher_context_t *ctx ) +static inline int mbedtls_cipher_get_iv_size( + const mbedtls_cipher_context_t *ctx ) { - if( NULL == ctx || NULL == ctx->cipher_info ) + MBEDTLS_INTERNAL_VALIDATE_RET( ctx != NULL, 0 ); + if( ctx->cipher_info == NULL ) return 0; if( ctx->iv_size != 0 ) @@ -459,14 +479,17 @@ static inline int mbedtls_cipher_get_iv_size( const mbedtls_cipher_context_t *ct /** * \brief This function returns the type of the given cipher. * - * \param ctx The context of the cipher. Must be initialized. + * \param ctx The context of the cipher. This must be initialized. * * \return The type of the cipher. * \return #MBEDTLS_CIPHER_NONE if \p ctx has not been initialized. */ -static inline mbedtls_cipher_type_t mbedtls_cipher_get_type( const mbedtls_cipher_context_t *ctx ) +static inline mbedtls_cipher_type_t mbedtls_cipher_get_type( + const mbedtls_cipher_context_t *ctx ) { - if( NULL == ctx || NULL == ctx->cipher_info ) + MBEDTLS_INTERNAL_VALIDATE_RET( + ctx != NULL, MBEDTLS_CIPHER_NONE ); + if( ctx->cipher_info == NULL ) return MBEDTLS_CIPHER_NONE; return ctx->cipher_info->type; @@ -476,14 +499,16 @@ static inline mbedtls_cipher_type_t mbedtls_cipher_get_type( const mbedtls_ciphe * \brief This function returns the name of the given cipher * as a string. * - * \param ctx The context of the cipher. Must be initialized. + * \param ctx The context of the cipher. This must be initialized. * * \return The name of the cipher. * \return NULL if \p ctx has not been not initialized. */ -static inline const char *mbedtls_cipher_get_name( const mbedtls_cipher_context_t *ctx ) +static inline const char *mbedtls_cipher_get_name( + const mbedtls_cipher_context_t *ctx ) { - if( NULL == ctx || NULL == ctx->cipher_info ) + MBEDTLS_INTERNAL_VALIDATE_RET( ctx != NULL, 0 ); + if( ctx->cipher_info == NULL ) return 0; return ctx->cipher_info->name; @@ -492,15 +517,18 @@ static inline const char *mbedtls_cipher_get_name( const mbedtls_cipher_context_ /** * \brief This function returns the key length of the cipher. * - * \param ctx The context of the cipher. Must be initialized. + * \param ctx The context of the cipher. This must be initialized. * * \return The key length of the cipher in bits. * \return #MBEDTLS_KEY_LENGTH_NONE if ctx \p has not been * initialized. */ -static inline int mbedtls_cipher_get_key_bitlen( const mbedtls_cipher_context_t *ctx ) +static inline int mbedtls_cipher_get_key_bitlen( + const mbedtls_cipher_context_t *ctx ) { - if( NULL == ctx || NULL == ctx->cipher_info ) + MBEDTLS_INTERNAL_VALIDATE_RET( + ctx != NULL, MBEDTLS_KEY_LENGTH_NONE ); + if( ctx->cipher_info == NULL ) return MBEDTLS_KEY_LENGTH_NONE; return (int) ctx->cipher_info->key_bitlen; @@ -509,14 +537,17 @@ static inline int mbedtls_cipher_get_key_bitlen( const mbedtls_cipher_context_t /** * \brief This function returns the operation of the given cipher. * - * \param ctx The context of the cipher. Must be initialized. + * \param ctx The context of the cipher. This must be initialized. * * \return The type of operation: #MBEDTLS_ENCRYPT or #MBEDTLS_DECRYPT. * \return #MBEDTLS_OPERATION_NONE if \p ctx has not been initialized. */ -static inline mbedtls_operation_t mbedtls_cipher_get_operation( const mbedtls_cipher_context_t *ctx ) +static inline mbedtls_operation_t mbedtls_cipher_get_operation( + const mbedtls_cipher_context_t *ctx ) { - if( NULL == ctx || NULL == ctx->cipher_info ) + MBEDTLS_INTERNAL_VALIDATE_RET( + ctx != NULL, MBEDTLS_OPERATION_NONE ); + if( ctx->cipher_info == NULL ) return MBEDTLS_OPERATION_NONE; return ctx->operation; @@ -525,11 +556,11 @@ static inline mbedtls_operation_t mbedtls_cipher_get_operation( const mbedtls_ci /** * \brief This function sets the key to use with the given context. * - * \param ctx The generic cipher context. May not be NULL. Must have - * been initialized using mbedtls_cipher_info_from_type() - * or mbedtls_cipher_info_from_string(). - * \param key The key to use. - * \param key_bitlen The key length to use, in bits. + * \param ctx The generic cipher context. This must be initialized and + * bound to a cipher information structure. + * \param key The key to use. This must be a readable buffer of at + * least \p key_bitlen Bits. + * \param key_bitlen The key length to use, in Bits. * \param operation The operation that the key will be used for: * #MBEDTLS_ENCRYPT or #MBEDTLS_DECRYPT. * @@ -538,8 +569,10 @@ static inline mbedtls_operation_t mbedtls_cipher_get_operation( const mbedtls_ci * parameter-verification failure. * \return A cipher-specific error code on failure. */ -int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx, const unsigned char *key, - int key_bitlen, const mbedtls_operation_t operation ); +int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx, + const unsigned char *key, + int key_bitlen, + const mbedtls_operation_t operation ); #if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) /** @@ -548,7 +581,8 @@ int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx, const unsigned char *k * * The default passing mode is PKCS7 padding. * - * \param ctx The generic cipher context. + * \param ctx The generic cipher context. This must be initialized and + * bound to a cipher information structure. * \param mode The padding mode. * * \return \c 0 on success. @@ -557,7 +591,8 @@ int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx, const unsigned char *k * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA if the cipher mode * does not support padding. */ -int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx, mbedtls_cipher_padding_t mode ); +int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx, + mbedtls_cipher_padding_t mode ); #endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ /** @@ -567,8 +602,10 @@ int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx, mbedtls_ciph * \note Some ciphers do not use IVs nor nonce. For these * ciphers, this function has no effect. * - * \param ctx The generic cipher context. - * \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers. + * \param ctx The generic cipher context. This must be initialized and + * bound to a cipher information structure. + * \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers. This + * must be a readable buffer of at least \p iv_len Bytes. * \param iv_len The IV length for ciphers with variable-size IV. * This parameter is discarded by ciphers with fixed-size IV. * @@ -577,12 +614,13 @@ int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx, mbedtls_ciph * parameter-verification failure. */ int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx, - const unsigned char *iv, size_t iv_len ); + const unsigned char *iv, + size_t iv_len ); /** * \brief This function resets the cipher state. * - * \param ctx The generic cipher context. + * \param ctx The generic cipher context. This must be initialized. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on @@ -594,11 +632,13 @@ int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx ); /** * \brief This function adds additional data for AEAD ciphers. * Currently supported with GCM and ChaCha20+Poly1305. - * Must be called exactly once, after mbedtls_cipher_reset(). + * This must be called exactly once, after + * mbedtls_cipher_reset(). * - * \param ctx The generic cipher context. - * \param ad The additional data to use. - * \param ad_len the Length of \p ad. + * \param ctx The generic cipher context. This must be initialized. + * \param ad The additional data to use. This must be a readable + * buffer of at least \p ad_len Bytes. + * \param ad_len the Length of \p ad Bytes. * * \return \c 0 on success. * \return A specific error code on failure. @@ -622,14 +662,17 @@ int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx, * mbedtls_cipher_finish(), must have \p ilen as a * multiple of the block size of the cipher. * - * \param ctx The generic cipher context. - * \param input The buffer holding the input data. + * \param ctx The generic cipher context. This must be initialized and + * bound to a key. + * \param input The buffer holding the input data. This must be a + * readable buffer of at least \p ilen Bytes. * \param ilen The length of the input data. - * \param output The buffer for the output data. Must be able to hold at - * least \p ilen + block_size. Must not be the same buffer - * as input. + * \param output The buffer for the output data. This must be able to + * hold at least `ilen + block_size`. This must not be the + * same buffer as \p input. * \param olen The length of the output data, to be updated with the - * actual number of Bytes written. + * actual number of Bytes written. This must not be + * \c NULL. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on @@ -647,9 +690,12 @@ int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *i * contained in it is padded to the size of * the last block, and written to the \p output buffer. * - * \param ctx The generic cipher context. - * \param output The buffer to write data to. Needs block_size available. + * \param ctx The generic cipher context. This must be initialized and + * bound to a key. + * \param output The buffer to write data to. This needs to be a writable + * buffer of at least \p block_size Bytes. * \param olen The length of the data written to the \p output buffer. + * This may not be \c NULL. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on @@ -667,10 +713,14 @@ int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx, /** * \brief This function writes a tag for AEAD ciphers. * Currently supported with GCM and ChaCha20+Poly1305. - * Must be called after mbedtls_cipher_finish(). - * - * \param ctx The generic cipher context. - * \param tag The buffer to write the tag to. + * This must be called after mbedtls_cipher_finish(). + * + * \param ctx The generic cipher context. This must be initialized, + * bound to a key, and have just completed a cipher + * operation through mbedtls_cipher_finish() the tag for + * which should be written. + * \param tag The buffer to write the tag to. This must be a writable + * buffer of at least \p tag_len Bytes. * \param tag_len The length of the tag to write. * * \return \c 0 on success. @@ -682,10 +732,11 @@ int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx, /** * \brief This function checks the tag for AEAD ciphers. * Currently supported with GCM and ChaCha20+Poly1305. - * Must be called after mbedtls_cipher_finish(). + * This must be called after mbedtls_cipher_finish(). * - * \param ctx The generic cipher context. - * \param tag The buffer holding the tag. + * \param ctx The generic cipher context. This must be initialized. + * \param tag The buffer holding the tag. This must be a readable + * buffer of at least \p tag_len Bytes. * \param tag_len The length of the tag to check. * * \return \c 0 on success. @@ -699,18 +750,22 @@ int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx, * \brief The generic all-in-one encryption/decryption function, * for all ciphers except AEAD constructs. * - * \param ctx The generic cipher context. + * \param ctx The generic cipher context. This must be initialized. * \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers. + * This must be a readable buffer of at least \p iv_len + * Bytes. * \param iv_len The IV length for ciphers with variable-size IV. * This parameter is discarded by ciphers with fixed-size * IV. - * \param input The buffer holding the input data. - * \param ilen The length of the input data. - * \param output The buffer for the output data. Must be able to hold at - * least \p ilen + block_size. Must not be the same buffer - * as input. + * \param input The buffer holding the input data. This must be a + * readable buffer of at least \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + * \param output The buffer for the output data. This must be able to + * hold at least `ilen + block_size`. This must not be the + * same buffer as \p input. * \param olen The length of the output data, to be updated with the - * actual number of Bytes written. + * actual number of Bytes written. This must not be + * \c NULL. * * \note Some ciphers do not use IVs nor nonce. For these * ciphers, use \p iv = NULL and \p iv_len = 0. @@ -733,19 +788,26 @@ int mbedtls_cipher_crypt( mbedtls_cipher_context_t *ctx, /** * \brief The generic autenticated encryption (AEAD) function. * - * \param ctx The generic cipher context. + * \param ctx The generic cipher context. This must be initialized and + * bound to a key. * \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers. + * This must be a readable buffer of at least \p iv_len + * Bytes. * \param iv_len The IV length for ciphers with variable-size IV. * This parameter is discarded by ciphers with fixed-size IV. - * \param ad The additional data to authenticate. + * \param ad The additional data to authenticate. This must be a + * readable buffer of at least \p ad_len Bytes. * \param ad_len The length of \p ad. - * \param input The buffer holding the input data. + * \param input The buffer holding the input data. This must be a + * readable buffer of at least \p ilen Bytes. * \param ilen The length of the input data. - * \param output The buffer for the output data. - * Must be able to hold at least \p ilen. + * \param output The buffer for the output data. This must be able to + * hold at least \p ilen Bytes. * \param olen The length of the output data, to be updated with the - * actual number of Bytes written. - * \param tag The buffer for the authentication tag. + * actual number of Bytes written. This must not be + * \c NULL. + * \param tag The buffer for the authentication tag. This must be a + * writable buffer of at least \p tag_len Bytes. * \param tag_len The desired length of the authentication tag. * * \return \c 0 on success. @@ -767,19 +829,26 @@ int mbedtls_cipher_auth_encrypt( mbedtls_cipher_context_t *ctx, * is zeroed out to prevent the unauthentic plaintext being * used, making this interface safer. * - * \param ctx The generic cipher context. + * \param ctx The generic cipher context. This must be initialized and + * and bound to a key. * \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers. + * This must be a readable buffer of at least \p iv_len + * Bytes. * \param iv_len The IV length for ciphers with variable-size IV. * This parameter is discarded by ciphers with fixed-size IV. - * \param ad The additional data to be authenticated. + * \param ad The additional data to be authenticated. This must be a + * readable buffer of at least \p ad_len Bytes. * \param ad_len The length of \p ad. - * \param input The buffer holding the input data. + * \param input The buffer holding the input data. This must be a + * readable buffer of at least \p ilen Bytes. * \param ilen The length of the input data. * \param output The buffer for the output data. - * Must be able to hold at least \p ilen. + * This must be able to hold at least \p ilen Bytes. * \param olen The length of the output data, to be updated with the - * actual number of Bytes written. - * \param tag The buffer holding the authentication tag. + * actual number of Bytes written. This must not be + * \c NULL. + * \param tag The buffer holding the authentication tag. This must be + * a readable buffer of at least \p tag_len Bytes. * \param tag_len The length of the authentication tag. * * \return \c 0 on success. diff --git a/thirdparty/mbedtls/include/mbedtls/cmac.h b/thirdparty/mbedtls/include/mbedtls/cmac.h index a4fd552565..c196793531 100644 --- a/thirdparty/mbedtls/include/mbedtls/cmac.h +++ b/thirdparty/mbedtls/include/mbedtls/cmac.h @@ -34,6 +34,7 @@ extern "C" { #endif +/* MBEDTLS_ERR_CMAC_HW_ACCEL_FAILED is deprecated and should not be used. */ #define MBEDTLS_ERR_CMAC_HW_ACCEL_FAILED -0x007A /**< CMAC hardware accelerator failed. */ #define MBEDTLS_AES_BLOCK_SIZE 16 diff --git a/thirdparty/mbedtls/include/mbedtls/config.h b/thirdparty/mbedtls/include/mbedtls/config.h index 6daa8d103b..91cc5bddf8 100644 --- a/thirdparty/mbedtls/include/mbedtls/config.h +++ b/thirdparty/mbedtls/include/mbedtls/config.h @@ -137,12 +137,21 @@ /** * \def MBEDTLS_HAVE_TIME_DATE * - * System has time.h and time(), gmtime() and the clock is correct. + * System has time.h, time(), and an implementation for + * mbedtls_platform_gmtime_r() (see below). * The time needs to be correct (not necesarily very accurate, but at least * the date should be correct). This is used to verify the validity period of * X.509 certificates. * * Comment if your system does not have a correct clock. + * + * \note mbedtls_platform_gmtime_r() is an abstraction in platform_util.h that + * behaves similarly to the gmtime_r() function from the C standard. Refer to + * the documentation for mbedtls_platform_gmtime_r() for more information. + * + * \note It is possible to configure an implementation for + * mbedtls_platform_gmtime_r() at compile-time by using the macro + * MBEDTLS_PLATFORM_GMTIME_R_ALT. */ #define MBEDTLS_HAVE_TIME_DATE @@ -247,6 +256,48 @@ */ //#define MBEDTLS_DEPRECATED_REMOVED +/** + * \def MBEDTLS_CHECK_PARAMS + * + * This configuration option controls whether the library validates more of + * the parameters passed to it. + * + * When this flag is not defined, the library only attempts to validate an + * input parameter if: (1) they may come from the outside world (such as the + * network, the filesystem, etc.) or (2) not validating them could result in + * internal memory errors such as overflowing a buffer controlled by the + * library. On the other hand, it doesn't attempt to validate parameters whose + * values are fully controlled by the application (such as pointers). + * + * When this flag is defined, the library additionally attempts to validate + * parameters that are fully controlled by the application, and should always + * be valid if the application code is fully correct and trusted. + * + * For example, when a function accepts as input a pointer to a buffer that may + * contain untrusted data, and its documentation mentions that this pointer + * must not be NULL: + * - the pointer is checked to be non-NULL only if this option is enabled + * - the content of the buffer is always validated + * + * When this flag is defined, if a library function receives a parameter that + * is invalid, it will: + * - invoke the macro MBEDTLS_PARAM_FAILED() which by default expands to a + * call to the function mbedtls_param_failed() + * - immediately return (with a specific error code unless the function + * returns void and can't communicate an error). + * + * When defining this flag, you also need to: + * - either provide a definition of the function mbedtls_param_failed() in + * your application (see platform_util.h for its prototype) as the library + * calls that function, but does not provide a default definition for it, + * - or provide a different definition of the macro MBEDTLS_PARAM_FAILED() + * below if the above mechanism is not flexible enough to suit your needs. + * See the documentation of this macro later in this file. + * + * Uncomment to enable validation of application-controlled parameters. + */ +//#define MBEDTLS_CHECK_PARAMS + /* \} name SECTION: System support */ /** @@ -405,11 +456,11 @@ * unsigned char mbedtls_internal_ecp_grp_capable( * const mbedtls_ecp_group *grp ) * int mbedtls_internal_ecp_init( const mbedtls_ecp_group *grp ) - * void mbedtls_internal_ecp_deinit( const mbedtls_ecp_group *grp ) + * void mbedtls_internal_ecp_free( const mbedtls_ecp_group *grp ) * The mbedtls_internal_ecp_grp_capable function should return 1 if the * replacement functions implement arithmetic for the given group and 0 * otherwise. - * The functions mbedtls_internal_ecp_init and mbedtls_internal_ecp_deinit are + * The functions mbedtls_internal_ecp_init and mbedtls_internal_ecp_free are * called before and after each point operation and provide an opportunity to * implement optimized set up and tear down instructions. * @@ -669,6 +720,30 @@ #define MBEDTLS_ECP_NIST_OPTIM /** + * \def MBEDTLS_ECP_RESTARTABLE + * + * Enable "non-blocking" ECC operations that can return early and be resumed. + * + * This allows various functions to pause by returning + * #MBEDTLS_ERR_ECP_IN_PROGRESS (or, for functions in the SSL module, + * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS) and then be called later again in + * order to further progress and eventually complete their operation. This is + * controlled through mbedtls_ecp_set_max_ops() which limits the maximum + * number of ECC operations a function may perform before pausing; see + * mbedtls_ecp_set_max_ops() for more information. + * + * This is useful in non-threaded environments if you want to avoid blocking + * for too long on ECC (and, hence, X.509 or SSL/TLS) operations. + * + * Uncomment this macro to enable restartable ECC computations. + * + * \note This option only works with the default software implementation of + * elliptic curve functionality. It is incompatible with + * MBEDTLS_ECP_ALT, MBEDTLS_ECDH_XXX_ALT and MBEDTLS_ECDSA_XXX_ALT. + */ +//#define MBEDTLS_ECP_RESTARTABLE + +/** * \def MBEDTLS_ECDSA_DETERMINISTIC * * Enable deterministic ECDSA (RFC 6979). @@ -1279,7 +1354,7 @@ /** * \def MBEDTLS_SSL_RENEGOTIATION * - * Disable support for TLS renegotiation. + * Enable support for TLS renegotiation. * * The two main uses of renegotiation are (1) refresh keys on long-lived * connections and (2) client authentication after the initial handshake. @@ -2018,14 +2093,16 @@ /** * \def MBEDTLS_CTR_DRBG_C * - * Enable the CTR_DRBG AES-256-based random generator. + * Enable the CTR_DRBG AES-based random generator. + * The CTR_DRBG generator uses AES-256 by default. + * To use AES-128 instead, enable MBEDTLS_CTR_DRBG_USE_128_BIT_KEY below. * * Module: library/ctr_drbg.c * Caller: * * Requires: MBEDTLS_AES_C * - * This module provides the CTR_DRBG AES-256 random number generator. + * This module provides the CTR_DRBG AES random number generator. */ #define MBEDTLS_CTR_DRBG_C @@ -2389,6 +2466,20 @@ #define MBEDTLS_OID_C /** + * \def MBEDTLS_PADLOCK_C + * + * Enable VIA Padlock support on x86. + * + * Module: library/padlock.c + * Caller: library/aes.c + * + * Requires: MBEDTLS_HAVE_ASM + * + * This modules adds support for the VIA PadLock on x86. + */ +#define MBEDTLS_PADLOCK_C + +/** * \def MBEDTLS_PEM_PARSE_C * * Enable PEM decoding / parsing. @@ -2896,6 +2987,7 @@ //#define MBEDTLS_CTR_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ //#define MBEDTLS_CTR_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ //#define MBEDTLS_CTR_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ +//#define MBEDTLS_CTR_DRBG_USE_128_BIT_KEY /**< Use 128-bit key for CTR_DRBG - may reduce security (see ctr_drbg.h) */ /* HMAC_DRBG options */ //#define MBEDTLS_HMAC_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ @@ -2946,6 +3038,36 @@ //#define MBEDTLS_PLATFORM_NV_SEED_READ_MACRO mbedtls_platform_std_nv_seed_read /**< Default nv_seed_read function to use, can be undefined */ //#define MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO mbedtls_platform_std_nv_seed_write /**< Default nv_seed_write function to use, can be undefined */ +/** + * \brief This macro is invoked by the library when an invalid parameter + * is detected that is only checked with MBEDTLS_CHECK_PARAMS + * (see the documentation of that option for context). + * + * When you leave this undefined here, a default definition is + * provided that invokes the function mbedtls_param_failed(), + * which is declared in platform_util.h for the benefit of the + * library, but that you need to define in your application. + * + * When you define this here, this replaces the default + * definition in platform_util.h (which no longer declares the + * function mbedtls_param_failed()) and it is your responsibility + * to make sure this macro expands to something suitable (in + * particular, that all the necessary declarations are visible + * from within the library - you can ensure that by providing + * them in this file next to the macro definition). + * + * Note that you may define this macro to expand to nothing, in + * which case you don't have to worry about declarations or + * definitions. However, you will then be notified about invalid + * parameters only in non-void functions, and void function will + * just silently return early on invalid parameters, which + * partially negates the benefits of enabling + * #MBEDTLS_CHECK_PARAMS in the first place, so is discouraged. + * + * \param cond The expression that should evaluate to true, but doesn't. + */ +//#define MBEDTLS_PARAM_FAILED( cond ) assert( cond ) + /* SSL Cache options */ //#define MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT 86400 /**< 1 day */ //#define MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES 50 /**< Maximum entries in cache */ @@ -2954,31 +3076,65 @@ /** \def MBEDTLS_SSL_MAX_CONTENT_LEN * - * Maximum fragment length in bytes. + * Maximum length (in bytes) of incoming and outgoing plaintext fragments. + * + * This determines the size of both the incoming and outgoing TLS I/O buffers + * in such a way that both are capable of holding the specified amount of + * plaintext data, regardless of the protection mechanism used. * - * Determines the size of both the incoming and outgoing TLS I/O buffers. + * To configure incoming and outgoing I/O buffers separately, use + * #MBEDTLS_SSL_IN_CONTENT_LEN and #MBEDTLS_SSL_OUT_CONTENT_LEN, + * which overwrite the value set by this option. * - * Uncommenting MBEDTLS_SSL_IN_CONTENT_LEN and/or MBEDTLS_SSL_OUT_CONTENT_LEN - * will override this length by setting maximum incoming and/or outgoing - * fragment length, respectively. + * \note When using a value less than the default of 16KB on the client, it is + * recommended to use the Maximum Fragment Length (MFL) extension to + * inform the server about this limitation. On the server, there + * is no supported, standardized way of informing the client about + * restriction on the maximum size of incoming messages, and unless + * the limitation has been communicated by other means, it is recommended + * to only change the outgoing buffer size #MBEDTLS_SSL_OUT_CONTENT_LEN + * while keeping the default value of 16KB for the incoming buffer. + * + * Uncomment to set the maximum plaintext size of both + * incoming and outgoing I/O buffers. */ //#define MBEDTLS_SSL_MAX_CONTENT_LEN 16384 /** \def MBEDTLS_SSL_IN_CONTENT_LEN * - * Maximum incoming fragment length in bytes. + * Maximum length (in bytes) of incoming plaintext fragments. + * + * This determines the size of the incoming TLS I/O buffer in such a way + * that it is capable of holding the specified amount of plaintext data, + * regardless of the protection mechanism used. + * + * If this option is undefined, it inherits its value from + * #MBEDTLS_SSL_MAX_CONTENT_LEN. + * + * \note When using a value less than the default of 16KB on the client, it is + * recommended to use the Maximum Fragment Length (MFL) extension to + * inform the server about this limitation. On the server, there + * is no supported, standardized way of informing the client about + * restriction on the maximum size of incoming messages, and unless + * the limitation has been communicated by other means, it is recommended + * to only change the outgoing buffer size #MBEDTLS_SSL_OUT_CONTENT_LEN + * while keeping the default value of 16KB for the incoming buffer. * - * Uncomment to set the size of the inward TLS buffer independently of the - * outward buffer. + * Uncomment to set the maximum plaintext size of the incoming I/O buffer + * independently of the outgoing I/O buffer. */ //#define MBEDTLS_SSL_IN_CONTENT_LEN 16384 /** \def MBEDTLS_SSL_OUT_CONTENT_LEN * - * Maximum outgoing fragment length in bytes. + * Maximum length (in bytes) of outgoing plaintext fragments. * - * Uncomment to set the size of the outward TLS buffer independently of the - * inward buffer. + * This determines the size of the outgoing TLS I/O buffer in such a way + * that it is capable of holding the specified amount of plaintext data, + * regardless of the protection mechanism used. + * + * If this option undefined, it inherits its value from + * #MBEDTLS_SSL_MAX_CONTENT_LEN. * * It is possible to save RAM by setting a smaller outward buffer, while keeping * the default inward 16384 byte buffer to conform to the TLS specification. @@ -2988,14 +3144,28 @@ * The specific size requirement depends on the configured ciphers and any * certificate data which is sent during the handshake. * - * For absolute minimum RAM usage, it's best to enable - * MBEDTLS_SSL_MAX_FRAGMENT_LENGTH and reduce MBEDTLS_SSL_MAX_CONTENT_LEN. This - * reduces both incoming and outgoing buffer sizes. However this is only - * guaranteed if the other end of the connection also supports the TLS - * max_fragment_len extension. Otherwise the connection may fail. + * Uncomment to set the maximum plaintext size of the outgoing I/O buffer + * independently of the incoming I/O buffer. */ //#define MBEDTLS_SSL_OUT_CONTENT_LEN 16384 +/** \def MBEDTLS_SSL_DTLS_MAX_BUFFERING + * + * Maximum number of heap-allocated bytes for the purpose of + * DTLS handshake message reassembly and future message buffering. + * + * This should be at least 9/8 * MBEDTLSSL_IN_CONTENT_LEN + * to account for a reassembled handshake message of maximum size, + * together with its reassembly bitmap. + * + * A value of 2 * MBEDTLS_SSL_IN_CONTENT_LEN (32768 by default) + * should be sufficient for all practical situations as it allows + * to reassembly a large handshake message (such as a certificate) + * while buffering multiple smaller handshake messages. + * + */ +//#define MBEDTLS_SSL_DTLS_MAX_BUFFERING 32768 + //#define MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME 86400 /**< Lifetime of session tickets (if enabled) */ //#define MBEDTLS_PSK_MAX_LEN 32 /**< Max size of TLS pre-shared keys, in bytes (default 256 bits) */ //#define MBEDTLS_SSL_COOKIE_TIMEOUT 60 /**< Default expiration delay of DTLS cookies, in seconds if HAVE_TIME, or in number of cookies issued */ @@ -3069,25 +3239,33 @@ */ //#define MBEDTLS_PLATFORM_ZEROIZE_ALT -/* \} name SECTION: Customisation configuration options */ - -/* Target and application specific configurations */ -//#define YOTTA_CFG_MBEDTLS_TARGET_CONFIG_FILE "target_config.h" +/** + * Uncomment the macro to let Mbed TLS use your alternate implementation of + * mbedtls_platform_gmtime_r(). This replaces the default implementation in + * platform_util.c. + * + * gmtime() is not a thread-safe function as defined in the C standard. The + * library will try to use safer implementations of this function, such as + * gmtime_r() when available. However, if Mbed TLS cannot identify the target + * system, the implementation of mbedtls_platform_gmtime_r() will default to + * using the standard gmtime(). In this case, calls from the library to + * gmtime() will be guarded by the global mutex mbedtls_threading_gmtime_mutex + * if MBEDTLS_THREADING_C is enabled. We recommend that calls from outside the + * library are also guarded with this mutex to avoid race conditions. However, + * if the macro MBEDTLS_PLATFORM_GMTIME_R_ALT is defined, Mbed TLS will + * unconditionally use the implementation for mbedtls_platform_gmtime_r() + * supplied at compile time. + */ +//#define MBEDTLS_PLATFORM_GMTIME_R_ALT -#if defined(TARGET_LIKE_MBED) && defined(YOTTA_CFG_MBEDTLS_TARGET_CONFIG_FILE) -#include YOTTA_CFG_MBEDTLS_TARGET_CONFIG_FILE -#endif +/* \} name SECTION: Customisation configuration options */ -/* +/* Target and application specific configurations + * * Allow user to override any previous default. * - * Use two macro names for that, as: - * - with yotta the prefix YOTTA_CFG_ is forced - * - without yotta is looks weird to have a YOTTA prefix. */ -#if defined(YOTTA_CFG_MBEDTLS_USER_CONFIG_FILE) -#include YOTTA_CFG_MBEDTLS_USER_CONFIG_FILE -#elif defined(MBEDTLS_USER_CONFIG_FILE) +#if defined(MBEDTLS_USER_CONFIG_FILE) #include MBEDTLS_USER_CONFIG_FILE #endif diff --git a/thirdparty/mbedtls/include/mbedtls/ctr_drbg.h b/thirdparty/mbedtls/include/mbedtls/ctr_drbg.h index 3835d7299b..10f9389d9f 100644 --- a/thirdparty/mbedtls/include/mbedtls/ctr_drbg.h +++ b/thirdparty/mbedtls/include/mbedtls/ctr_drbg.h @@ -8,8 +8,11 @@ * Recommendation for Random Number Generation Using Deterministic Random * Bit Generators</em>. * - * The Mbed TLS implementation of CTR_DRBG uses AES-256 as the underlying - * block cipher. + * The Mbed TLS implementation of CTR_DRBG uses AES-256 (default) or AES-128 + * as the underlying block cipher. + * + * \warning Using 128-bit keys for CTR_DRBG limits the security of generated + * keys and operations that use random values generated to 128-bit security. */ /* * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved @@ -45,7 +48,13 @@ #define MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR -0x003A /**< Read or write error in file. */ #define MBEDTLS_CTR_DRBG_BLOCKSIZE 16 /**< The block size used by the cipher. */ -#define MBEDTLS_CTR_DRBG_KEYSIZE 32 /**< The key size used by the cipher. */ + +#if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY) +#define MBEDTLS_CTR_DRBG_KEYSIZE 16 /**< The key size used by the cipher (compile-time choice: 128 bits). */ +#else +#define MBEDTLS_CTR_DRBG_KEYSIZE 32 /**< The key size used by the cipher (compile-time choice: 256 bits). */ +#endif + #define MBEDTLS_CTR_DRBG_KEYBITS ( MBEDTLS_CTR_DRBG_KEYSIZE * 8 ) /**< The key size for the DRBG operation, in bits. */ #define MBEDTLS_CTR_DRBG_SEEDLEN ( MBEDTLS_CTR_DRBG_KEYSIZE + MBEDTLS_CTR_DRBG_BLOCKSIZE ) /**< The seed length, calculated as (counter + AES key). */ @@ -108,7 +117,7 @@ extern "C" { /** * \brief The CTR_DRBG context structure. */ -typedef struct +typedef struct mbedtls_ctr_drbg_context { unsigned char counter[16]; /*!< The counter (V). */ int reseed_counter; /*!< The reseed counter. */ @@ -230,18 +239,20 @@ int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx, /** * \brief This function updates the state of the CTR_DRBG context. * - * \note If \p add_len is greater than - * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT, only the first - * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT Bytes are used. - * The remaining Bytes are silently discarded. - * * \param ctx The CTR_DRBG context. * \param additional The data to update the state with. - * \param add_len Length of \p additional data. - * + * \param add_len Length of \p additional in bytes. This must be at + * most #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG if + * \p add_len is more than + * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT. + * \return An error from the underlying AES cipher on failure. */ -void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx, - const unsigned char *additional, size_t add_len ); +int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx, + const unsigned char *additional, + size_t add_len ); /** * \brief This function updates a CTR_DRBG instance with additional @@ -281,6 +292,35 @@ int mbedtls_ctr_drbg_random_with_add( void *p_rng, int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len ); + +#if ! defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief This function updates the state of the CTR_DRBG context. + * + * \deprecated Superseded by mbedtls_ctr_drbg_update_ret() + * in 2.16.0. + * + * \note If \p add_len is greater than + * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT, only the first + * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT Bytes are used. + * The remaining Bytes are silently discarded. + * + * \param ctx The CTR_DRBG context. + * \param additional The data to update the state with. + * \param add_len Length of \p additional data. + */ +MBEDTLS_DEPRECATED void mbedtls_ctr_drbg_update( + mbedtls_ctr_drbg_context *ctx, + const unsigned char *additional, + size_t add_len ); +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + #if defined(MBEDTLS_FS_IO) /** * \brief This function writes a seed file. diff --git a/thirdparty/mbedtls/include/mbedtls/debug.h b/thirdparty/mbedtls/include/mbedtls/debug.h index ef8db67ff1..736444bb76 100644 --- a/thirdparty/mbedtls/include/mbedtls/debug.h +++ b/thirdparty/mbedtls/include/mbedtls/debug.h @@ -65,6 +65,11 @@ mbedtls_debug_print_crt( ssl, level, __FILE__, __LINE__, text, crt ) #endif +#if defined(MBEDTLS_ECDH_C) +#define MBEDTLS_SSL_DEBUG_ECDH( level, ecdh, attr ) \ + mbedtls_debug_printf_ecdh( ssl, level, __FILE__, __LINE__, ecdh, attr ) +#endif + #else /* MBEDTLS_DEBUG_C */ #define MBEDTLS_SSL_DEBUG_MSG( level, args ) do { } while( 0 ) @@ -73,6 +78,7 @@ #define MBEDTLS_SSL_DEBUG_MPI( level, text, X ) do { } while( 0 ) #define MBEDTLS_SSL_DEBUG_ECP( level, text, X ) do { } while( 0 ) #define MBEDTLS_SSL_DEBUG_CRT( level, text, crt ) do { } while( 0 ) +#define MBEDTLS_SSL_DEBUG_ECDH( level, ecdh, attr ) do { } while( 0 ) #endif /* MBEDTLS_DEBUG_C */ @@ -221,6 +227,36 @@ void mbedtls_debug_print_crt( const mbedtls_ssl_context *ssl, int level, const char *text, const mbedtls_x509_crt *crt ); #endif +#if defined(MBEDTLS_ECDH_C) +typedef enum +{ + MBEDTLS_DEBUG_ECDH_Q, + MBEDTLS_DEBUG_ECDH_QP, + MBEDTLS_DEBUG_ECDH_Z, +} mbedtls_debug_ecdh_attr; + +/** + * \brief Print a field of the ECDH structure in the SSL context to the debug + * output. This function is always used through the + * MBEDTLS_SSL_DEBUG_ECDH() macro, which supplies the ssl context, file + * and line number parameters. + * + * \param ssl SSL context + * \param level error level of the debug message + * \param file file the error has occurred in + * \param line line number the error has occurred in + * \param ecdh the ECDH context + * \param attr the identifier of the attribute being output + * + * \attention This function is intended for INTERNAL usage within the + * library only. + */ +void mbedtls_debug_printf_ecdh( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const mbedtls_ecdh_context *ecdh, + mbedtls_debug_ecdh_attr attr ); +#endif + #ifdef __cplusplus } #endif diff --git a/thirdparty/mbedtls/include/mbedtls/des.h b/thirdparty/mbedtls/include/mbedtls/des.h index 6eb7d03bae..d62042d14e 100644 --- a/thirdparty/mbedtls/include/mbedtls/des.h +++ b/thirdparty/mbedtls/include/mbedtls/des.h @@ -42,6 +42,8 @@ #define MBEDTLS_DES_DECRYPT 0 #define MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH -0x0032 /**< The data input has an invalid length. */ + +/* MBEDTLS_ERR_DES_HW_ACCEL_FAILED is deprecated and should not be used. */ #define MBEDTLS_ERR_DES_HW_ACCEL_FAILED -0x0033 /**< DES hardware accelerator failed. */ #define MBEDTLS_DES_KEY_SIZE 8 @@ -61,7 +63,7 @@ extern "C" { * security risk. We recommend considering stronger ciphers * instead. */ -typedef struct +typedef struct mbedtls_des_context { uint32_t sk[32]; /*!< DES subkeys */ } @@ -70,7 +72,7 @@ mbedtls_des_context; /** * \brief Triple-DES context structure */ -typedef struct +typedef struct mbedtls_des3_context { uint32_t sk[96]; /*!< 3DES subkeys */ } diff --git a/thirdparty/mbedtls/include/mbedtls/dhm.h b/thirdparty/mbedtls/include/mbedtls/dhm.h index 75317a8e6d..a5452c199a 100644 --- a/thirdparty/mbedtls/include/mbedtls/dhm.h +++ b/thirdparty/mbedtls/include/mbedtls/dhm.h @@ -84,7 +84,10 @@ #define MBEDTLS_ERR_DHM_INVALID_FORMAT -0x3380 /**< The ASN.1 data is not formatted correctly. */ #define MBEDTLS_ERR_DHM_ALLOC_FAILED -0x3400 /**< Allocation of memory failed. */ #define MBEDTLS_ERR_DHM_FILE_IO_ERROR -0x3480 /**< Read or write of file failed. */ + +/* MBEDTLS_ERR_DHM_HW_ACCEL_FAILED is deprecated and should not be used. */ #define MBEDTLS_ERR_DHM_HW_ACCEL_FAILED -0x3500 /**< DHM hardware accelerator failed. */ + #define MBEDTLS_ERR_DHM_SET_GROUP_FAILED -0x3580 /**< Setting the modulus and generator failed. */ #ifdef __cplusplus @@ -96,7 +99,7 @@ extern "C" { /** * \brief The DHM context structure. */ -typedef struct +typedef struct mbedtls_dhm_context { size_t len; /*!< The size of \p P in Bytes. */ mbedtls_mpi P; /*!< The prime modulus. */ @@ -124,9 +127,15 @@ mbedtls_dhm_context; void mbedtls_dhm_init( mbedtls_dhm_context *ctx ); /** - * \brief This function parses the ServerKeyExchange parameters. + * \brief This function parses the DHM parameters in a + * TLS ServerKeyExchange handshake message + * (DHM modulus, generator, and public key). * - * \param ctx The DHM context. + * \note In a TLS handshake, this is the how the client + * sets up its DHM context from the server's public + * DHM key material. + * + * \param ctx The DHM context to use. This must be initialized. * \param p On input, *p must be the start of the input buffer. * On output, *p is updated to point to the end of the data * that has been read. On success, this is the first byte @@ -140,31 +149,37 @@ void mbedtls_dhm_init( mbedtls_dhm_context *ctx ); * \return An \c MBEDTLS_ERR_DHM_XXX error code on failure. */ int mbedtls_dhm_read_params( mbedtls_dhm_context *ctx, - unsigned char **p, - const unsigned char *end ); + unsigned char **p, + const unsigned char *end ); /** - * \brief This function sets up and writes the ServerKeyExchange - * parameters. - * - * \note The destination buffer must be large enough to hold - * the reduced binary presentation of the modulus, the generator - * and the public key, each wrapped with a 2-byte length field. - * It is the responsibility of the caller to ensure that enough - * space is available. Refer to \c mbedtls_mpi_size to computing - * the byte-size of an MPI. + * \brief This function generates a DHM key pair and exports its + * public part together with the DHM parameters in the format + * used in a TLS ServerKeyExchange handshake message. * - * \note This function assumes that \c ctx->P and \c ctx->G - * have already been properly set. For that, use + * \note This function assumes that the DHM parameters \c ctx->P + * and \c ctx->G have already been properly set. For that, use * mbedtls_dhm_set_group() below in conjunction with * mbedtls_mpi_read_binary() and mbedtls_mpi_read_string(). * - * \param ctx The DHM context. + * \note In a TLS handshake, this is the how the server generates + * and exports its DHM key material. + * + * \param ctx The DHM context to use. This must be initialized + * and have the DHM parameters set. It may or may not + * already have imported the peer's public key. * \param x_size The private key size in Bytes. - * \param olen The number of characters written. - * \param output The destination buffer. - * \param f_rng The RNG function. - * \param p_rng The RNG context. + * \param olen The address at which to store the number of Bytes + * written on success. This must not be \c NULL. + * \param output The destination buffer. This must be a writable buffer of + * sufficient size to hold the reduced binary presentation of + * the modulus, the generator and the public key, each wrapped + * with a 2-byte length field. It is the responsibility of the + * caller to ensure that enough space is available. Refer to + * mbedtls_mpi_size() to computing the byte-size of an MPI. + * \param f_rng The RNG function. Must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng doesn't need a context parameter. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_DHM_XXX error code on failure. @@ -177,12 +192,14 @@ int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size, /** * \brief This function sets the prime modulus and generator. * - * \note This function can be used to set \p P, \p G + * \note This function can be used to set \c ctx->P, \c ctx->G * in preparation for mbedtls_dhm_make_params(). * - * \param ctx The DHM context. - * \param P The MPI holding the DHM prime modulus. - * \param G The MPI holding the DHM generator. + * \param ctx The DHM context to configure. This must be initialized. + * \param P The MPI holding the DHM prime modulus. This must be + * an initialized MPI. + * \param G The MPI holding the DHM generator. This must be an + * initialized MPI. * * \return \c 0 if successful. * \return An \c MBEDTLS_ERR_DHM_XXX error code on failure. @@ -192,11 +209,17 @@ int mbedtls_dhm_set_group( mbedtls_dhm_context *ctx, const mbedtls_mpi *G ); /** - * \brief This function imports the public value of the peer, G^Y. + * \brief This function imports the raw public value of the peer. + * + * \note In a TLS handshake, this is the how the server imports + * the Client's public DHM key. * - * \param ctx The DHM context. - * \param input The input buffer containing the G^Y value of the peer. - * \param ilen The size of the input buffer. + * \param ctx The DHM context to use. This must be initialized and have + * its DHM parameters set, e.g. via mbedtls_dhm_set_group(). + * It may or may not already have generated its own private key. + * \param input The input buffer containing the \c G^Y value of the peer. + * This must be a readable buffer of size \p ilen Bytes. + * \param ilen The size of the input buffer \p input in Bytes. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_DHM_XXX error code on failure. @@ -205,21 +228,25 @@ int mbedtls_dhm_read_public( mbedtls_dhm_context *ctx, const unsigned char *input, size_t ilen ); /** - * \brief This function creates its own private key, \c X, and - * exports \c G^X. + * \brief This function creates a DHM key pair and exports + * the raw public key in big-endian format. * * \note The destination buffer is always fully written * so as to contain a big-endian representation of G^X mod P. - * If it is larger than ctx->len, it is padded accordingly + * If it is larger than \c ctx->len, it is padded accordingly * with zero-bytes at the beginning. * - * \param ctx The DHM context. + * \param ctx The DHM context to use. This must be initialized and + * have the DHM parameters set. It may or may not already + * have imported the peer's public key. * \param x_size The private key size in Bytes. - * \param output The destination buffer. - * \param olen The length of the destination buffer. Must be at least - * equal to ctx->len (the size of \c P). - * \param f_rng The RNG function. - * \param p_rng The RNG context. + * \param output The destination buffer. This must be a writable buffer of + * size \p olen Bytes. + * \param olen The length of the destination buffer. This must be at least + * equal to `ctx->len` (the size of \c P). + * \param f_rng The RNG function. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be \c NULL + * if \p f_rng doesn't need a context argument. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_DHM_XXX error code on failure. @@ -230,22 +257,27 @@ int mbedtls_dhm_make_public( mbedtls_dhm_context *ctx, int x_size, void *p_rng ); /** - * \brief This function derives and exports the shared secret - * \c (G^Y)^X mod \c P. + * \brief This function derives and exports the shared secret + * \c (G^Y)^X mod \c P. * - * \note If \p f_rng is not NULL, it is used to blind the input as - * a countermeasure against timing attacks. Blinding is used - * only if our private key \c X is re-used, and not used - * otherwise. We recommend always passing a non-NULL - * \p f_rng argument. + * \note If \p f_rng is not \c NULL, it is used to blind the input as + * a countermeasure against timing attacks. Blinding is used + * only if our private key \c X is re-used, and not used + * otherwise. We recommend always passing a non-NULL + * \p f_rng argument. * - * \param ctx The DHM context. - * \param output The destination buffer. - * \param output_size The size of the destination buffer. Must be at least - * the size of ctx->len (the size of \c P). + * \param ctx The DHM context to use. This must be initialized + * and have its own private key generated and the peer's + * public key imported. + * \param output The buffer to write the generated shared key to. This + * must be a writable buffer of size \p output_size Bytes. + * \param output_size The size of the destination buffer. This must be at + * least the size of \c ctx->len (the size of \c P). * \param olen On exit, holds the actual number of Bytes written. - * \param f_rng The RNG function, for blinding purposes. - * \param p_rng The RNG context. + * \param f_rng The RNG function, for blinding purposes. This may + * b \c NULL if blinding isn't needed. + * \param p_rng The RNG context. This may be \c NULL if \p f_rng + * doesn't need a context argument. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_DHM_XXX error code on failure. @@ -256,9 +288,12 @@ int mbedtls_dhm_calc_secret( mbedtls_dhm_context *ctx, void *p_rng ); /** - * \brief This function frees and clears the components of a DHM context. + * \brief This function frees and clears the components + * of a DHM context. * - * \param ctx The DHM context to free and clear. + * \param ctx The DHM context to free and clear. This may be \c NULL, + * in which case this function is a no-op. If it is not \c NULL, + * it must point to an initialized DHM context. */ void mbedtls_dhm_free( mbedtls_dhm_context *ctx ); @@ -267,17 +302,19 @@ void mbedtls_dhm_free( mbedtls_dhm_context *ctx ); /** * \brief This function parses DHM parameters in PEM or DER format. * - * \param dhm The DHM context to initialize. - * \param dhmin The input buffer. - * \param dhminlen The size of the buffer, including the terminating null - * Byte for PEM data. + * \param dhm The DHM context to import the DHM parameters into. + * This must be initialized. + * \param dhmin The input buffer. This must be a readable buffer of + * length \p dhminlen Bytes. + * \param dhminlen The size of the input buffer \p dhmin, including the + * terminating \c NULL Byte for PEM data. * * \return \c 0 on success. - * \return An \c MBEDTLS_ERR_DHM_XXX or \c MBEDTLS_ERR_PEM_XXX error code - * error code on failure. + * \return An \c MBEDTLS_ERR_DHM_XXX or \c MBEDTLS_ERR_PEM_XXX error + * code on failure. */ int mbedtls_dhm_parse_dhm( mbedtls_dhm_context *dhm, const unsigned char *dhmin, - size_t dhminlen ); + size_t dhminlen ); #if defined(MBEDTLS_FS_IO) /** \ingroup x509_module */ @@ -285,11 +322,13 @@ int mbedtls_dhm_parse_dhm( mbedtls_dhm_context *dhm, const unsigned char *dhmin, * \brief This function loads and parses DHM parameters from a file. * * \param dhm The DHM context to load the parameters to. + * This must be initialized. * \param path The filename to read the DHM parameters from. + * This must not be \c NULL. * * \return \c 0 on success. - * \return An \c MBEDTLS_ERR_DHM_XXX or \c MBEDTLS_ERR_PEM_XXX error code - * error code on failure. + * \return An \c MBEDTLS_ERR_DHM_XXX or \c MBEDTLS_ERR_PEM_XXX + * error code on failure. */ int mbedtls_dhm_parse_dhmfile( mbedtls_dhm_context *dhm, const char *path ); #endif /* MBEDTLS_FS_IO */ @@ -350,15 +389,6 @@ int mbedtls_dhm_self_test( int verbose ); #if !defined(MBEDTLS_DEPRECATED_REMOVED) -#if defined(MBEDTLS_DEPRECATED_WARNING) -#define MBEDTLS_DEPRECATED __attribute__((deprecated)) -MBEDTLS_DEPRECATED typedef char const * mbedtls_deprecated_constant_t; -#define MBEDTLS_DEPRECATED_STRING_CONSTANT( VAL ) \ - ( (mbedtls_deprecated_constant_t) ( VAL ) ) -#else -#define MBEDTLS_DEPRECATED_STRING_CONSTANT( VAL ) VAL -#endif /* ! MBEDTLS_DEPRECATED_WARNING */ - /** * \warning The origin of the primes in RFC 5114 is not documented and * their use therefore constitutes a security risk! diff --git a/thirdparty/mbedtls/include/mbedtls/ecdh.h b/thirdparty/mbedtls/include/mbedtls/ecdh.h index 5fdf55a88a..05b2b03970 100644 --- a/thirdparty/mbedtls/include/mbedtls/ecdh.h +++ b/thirdparty/mbedtls/include/mbedtls/ecdh.h @@ -36,6 +36,18 @@ #include "ecp.h" +/* + * Use a backward compatible ECDH context. + * + * This flag is always enabled for now and future versions might add a + * configuration option that conditionally undefines this flag. + * The configuration option in question may have a different name. + * + * Features undefining this flag, must have a warning in their description in + * config.h stating that the feature breaks backward compatibility. + */ +#define MBEDTLS_ECDH_LEGACY_CONTEXT + #ifdef __cplusplus extern "C" { #endif @@ -49,11 +61,49 @@ typedef enum MBEDTLS_ECDH_THEIRS, /**< The key of the peer. */ } mbedtls_ecdh_side; +#if !defined(MBEDTLS_ECDH_LEGACY_CONTEXT) +/** + * Defines the ECDH implementation used. + * + * Later versions of the library may add new variants, therefore users should + * not make any assumptions about them. + */ +typedef enum +{ + MBEDTLS_ECDH_VARIANT_NONE = 0, /*!< Implementation not defined. */ + MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0,/*!< The default Mbed TLS implementation */ +} mbedtls_ecdh_variant; + +/** + * The context used by the default ECDH implementation. + * + * Later versions might change the structure of this context, therefore users + * should not make any assumptions about the structure of + * mbedtls_ecdh_context_mbed. + */ +typedef struct mbedtls_ecdh_context_mbed +{ + mbedtls_ecp_group grp; /*!< The elliptic curve used. */ + mbedtls_mpi d; /*!< The private key. */ + mbedtls_ecp_point Q; /*!< The public key. */ + mbedtls_ecp_point Qp; /*!< The value of the public key of the peer. */ + mbedtls_mpi z; /*!< The shared secret. */ +#if defined(MBEDTLS_ECP_RESTARTABLE) + mbedtls_ecp_restart_ctx rs; /*!< The restart context for EC computations. */ +#endif +} mbedtls_ecdh_context_mbed; +#endif + /** + * + * \warning Performing multiple operations concurrently on the same + * ECDSA context is not supported; objects of this type + * should not be shared between multiple threads. * \brief The ECDH context structure. */ -typedef struct +typedef struct mbedtls_ecdh_context { +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) mbedtls_ecp_group grp; /*!< The elliptic curve used. */ mbedtls_mpi d; /*!< The private key. */ mbedtls_ecp_point Q; /*!< The public key. */ @@ -63,6 +113,29 @@ typedef struct mbedtls_ecp_point Vi; /*!< The blinding value. */ mbedtls_ecp_point Vf; /*!< The unblinding value. */ mbedtls_mpi _d; /*!< The previous \p d. */ +#if defined(MBEDTLS_ECP_RESTARTABLE) + int restart_enabled; /*!< The flag for restartable mode. */ + mbedtls_ecp_restart_ctx rs; /*!< The restart context for EC computations. */ +#endif /* MBEDTLS_ECP_RESTARTABLE */ +#else + uint8_t point_format; /*!< The format of point export in TLS messages + as defined in RFC 4492. */ + mbedtls_ecp_group_id grp_id;/*!< The elliptic curve used. */ + mbedtls_ecdh_variant var; /*!< The ECDH implementation/structure used. */ + union + { + mbedtls_ecdh_context_mbed mbed_ecdh; + } ctx; /*!< Implementation-specific context. The + context in use is specified by the \c var + field. */ +#if defined(MBEDTLS_ECP_RESTARTABLE) + uint8_t restart_enabled; /*!< The flag for restartable mode. Functions of + an alternative implementation not supporting + restartable mode must return + MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED error + if this flag is set. */ +#endif /* MBEDTLS_ECP_RESTARTABLE */ +#endif /* MBEDTLS_ECDH_LEGACY_CONTEXT */ } mbedtls_ecdh_context; @@ -76,16 +149,20 @@ mbedtls_ecdh_context; * * \see ecp.h * - * \param grp The ECP group. + * \param grp The ECP group to use. This must be initialized and have + * domain parameters loaded, for example through + * mbedtls_ecp_load() or mbedtls_ecp_tls_read_group(). * \param d The destination MPI (private key). + * This must be initialized. * \param Q The destination point (public key). - * \param f_rng The RNG function. - * \param p_rng The RNG context. + * This must be initialized. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL in case \p f_rng doesn't need a context argument. * * \return \c 0 on success. - * \return An \c MBEDTLS_ERR_ECP_XXX or + * \return Another \c MBEDTLS_ERR_ECP_XXX or * \c MBEDTLS_MPI_XXX error code on failure. - * */ int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q, int (*f_rng)(void *, unsigned char *, size_t), @@ -104,15 +181,25 @@ int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp * countermeasures against side-channel attacks. * For more information, see mbedtls_ecp_mul(). * - * \param grp The ECP group. + * \param grp The ECP group to use. This must be initialized and have + * domain parameters loaded, for example through + * mbedtls_ecp_load() or mbedtls_ecp_tls_read_group(). * \param z The destination MPI (shared secret). + * This must be initialized. * \param Q The public key from another party. + * This must be initialized. * \param d Our secret exponent (private key). - * \param f_rng The RNG function. - * \param p_rng The RNG context. + * This must be initialized. + * \param f_rng The RNG function. This may be \c NULL if randomization + * of intermediate results during the ECP computations is + * not needed (discouraged). See the documentation of + * mbedtls_ecp_mul() for more. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng is \c NULL or doesn't need a + * context argument. * * \return \c 0 on success. - * \return An \c MBEDTLS_ERR_ECP_XXX or + * \return Another \c MBEDTLS_ERR_ECP_XXX or * \c MBEDTLS_MPI_XXX error code on failure. */ int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z, @@ -123,39 +210,62 @@ int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z, /** * \brief This function initializes an ECDH context. * - * \param ctx The ECDH context to initialize. + * \param ctx The ECDH context to initialize. This must not be \c NULL. */ void mbedtls_ecdh_init( mbedtls_ecdh_context *ctx ); /** + * \brief This function sets up the ECDH context with the information + * given. + * + * This function should be called after mbedtls_ecdh_init() but + * before mbedtls_ecdh_make_params(). There is no need to call + * this function before mbedtls_ecdh_read_params(). + * + * This is the first function used by a TLS server for ECDHE + * ciphersuites. + * + * \param ctx The ECDH context to set up. This must be initialized. + * \param grp_id The group id of the group to set up the context for. + * + * \return \c 0 on success. + */ +int mbedtls_ecdh_setup( mbedtls_ecdh_context *ctx, + mbedtls_ecp_group_id grp_id ); + +/** * \brief This function frees a context. * - * \param ctx The context to free. + * \param ctx The context to free. This may be \c NULL, in which + * case this function does nothing. If it is not \c NULL, + * it must point to an initialized ECDH context. */ void mbedtls_ecdh_free( mbedtls_ecdh_context *ctx ); /** - * \brief This function generates a public key and a TLS - * ServerKeyExchange payload. - * - * This is the first function used by a TLS server for ECDHE - * ciphersuites. + * \brief This function generates an EC key pair and exports its + * in the format used in a TLS ServerKeyExchange handshake + * message. * - * \note This function assumes that the ECP group (grp) of the - * \p ctx context has already been properly set, - * for example, using mbedtls_ecp_group_load(). + * This is the second function used by a TLS server for ECDHE + * ciphersuites. (It is called after mbedtls_ecdh_setup().) * * \see ecp.h * - * \param ctx The ECDH context. - * \param olen The number of characters written. - * \param buf The destination buffer. - * \param blen The length of the destination buffer. - * \param f_rng The RNG function. - * \param p_rng The RNG context. + * \param ctx The ECDH context to use. This must be initialized + * and bound to a group, for example via mbedtls_ecdh_setup(). + * \param olen The address at which to store the number of Bytes written. + * \param buf The destination buffer. This must be a writable buffer of + * length \p blen Bytes. + * \param blen The length of the destination buffer \p buf in Bytes. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL in case \p f_rng doesn't need a context argument. * * \return \c 0 on success. - * \return An \c MBEDTLS_ERR_ECP_XXX error code on failure. + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + * \return Another \c MBEDTLS_ERR_ECP_XXX error code on failure. */ int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen, unsigned char *buf, size_t blen, @@ -163,24 +273,32 @@ int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen, void *p_rng ); /** - * \brief This function parses and processes a TLS ServerKeyExhange - * payload. + * \brief This function parses the ECDHE parameters in a + * TLS ServerKeyExchange handshake message. * - * This is the first function used by a TLS client for ECDHE - * ciphersuites. + * \note In a TLS handshake, this is the how the client + * sets up its ECDHE context from the server's public + * ECDHE key material. * * \see ecp.h * - * \param ctx The ECDH context. - * \param buf The pointer to the start of the input buffer. - * \param end The address for one Byte past the end of the buffer. + * \param ctx The ECDHE context to use. This must be initialized. + * \param buf On input, \c *buf must be the start of the input buffer. + * On output, \c *buf is updated to point to the end of the + * data that has been read. On success, this is the first byte + * past the end of the ServerKeyExchange parameters. + * On error, this is the point at which an error has been + * detected, which is usually not useful except to debug + * failures. + * \param end The end of the input buffer. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_ECP_XXX error code on failure. * */ int mbedtls_ecdh_read_params( mbedtls_ecdh_context *ctx, - const unsigned char **buf, const unsigned char *end ); + const unsigned char **buf, + const unsigned char *end ); /** * \brief This function sets up an ECDH context from an EC key. @@ -191,36 +309,45 @@ int mbedtls_ecdh_read_params( mbedtls_ecdh_context *ctx, * * \see ecp.h * - * \param ctx The ECDH context to set up. - * \param key The EC key to use. - * \param side Defines the source of the key: 1: Our key, or - * 0: The key of the peer. + * \param ctx The ECDH context to set up. This must be initialized. + * \param key The EC key to use. This must be initialized. + * \param side Defines the source of the key. Possible values are: + * - #MBEDTLS_ECDH_OURS: The key is ours. + * - #MBEDTLS_ECDH_THEIRS: The key is that of the peer. * * \return \c 0 on success. - * \return An \c MBEDTLS_ERR_ECP_XXX error code on failure. + * \return Another \c MBEDTLS_ERR_ECP_XXX error code on failure. * */ -int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx, const mbedtls_ecp_keypair *key, - mbedtls_ecdh_side side ); +int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx, + const mbedtls_ecp_keypair *key, + mbedtls_ecdh_side side ); /** - * \brief This function generates a public key and a TLS - * ClientKeyExchange payload. + * \brief This function generates a public key and exports it + * as a TLS ClientKeyExchange payload. * * This is the second function used by a TLS client for ECDH(E) * ciphersuites. * * \see ecp.h * - * \param ctx The ECDH context. - * \param olen The number of Bytes written. - * \param buf The destination buffer. - * \param blen The size of the destination buffer. - * \param f_rng The RNG function. - * \param p_rng The RNG context. + * \param ctx The ECDH context to use. This must be initialized + * and bound to a group, the latter usually by + * mbedtls_ecdh_read_params(). + * \param olen The address at which to store the number of Bytes written. + * This must not be \c NULL. + * \param buf The destination buffer. This must be a writable buffer + * of length \p blen Bytes. + * \param blen The size of the destination buffer \p buf in Bytes. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL in case \p f_rng doesn't need a context argument. * * \return \c 0 on success. - * \return An \c MBEDTLS_ERR_ECP_XXX error code on failure. + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + * \return Another \c MBEDTLS_ERR_ECP_XXX error code on failure. */ int mbedtls_ecdh_make_public( mbedtls_ecdh_context *ctx, size_t *olen, unsigned char *buf, size_t blen, @@ -228,23 +355,26 @@ int mbedtls_ecdh_make_public( mbedtls_ecdh_context *ctx, size_t *olen, void *p_rng ); /** - * \brief This function parses and processes a TLS ClientKeyExchange - * payload. + * \brief This function parses and processes the ECDHE payload of a + * TLS ClientKeyExchange message. * - * This is the second function used by a TLS server for ECDH(E) - * ciphersuites. + * This is the third function used by a TLS server for ECDH(E) + * ciphersuites. (It is called after mbedtls_ecdh_setup() and + * mbedtls_ecdh_make_params().) * * \see ecp.h * - * \param ctx The ECDH context. - * \param buf The start of the input buffer. - * \param blen The length of the input buffer. + * \param ctx The ECDH context to use. This must be initialized + * and bound to a group, for example via mbedtls_ecdh_setup(). + * \param buf The pointer to the ClientKeyExchange payload. This must + * be a readable buffer of length \p blen Bytes. + * \param blen The length of the input buffer \p buf in Bytes. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_ECP_XXX error code on failure. */ int mbedtls_ecdh_read_public( mbedtls_ecdh_context *ctx, - const unsigned char *buf, size_t blen ); + const unsigned char *buf, size_t blen ); /** * \brief This function derives and exports the shared secret. @@ -257,22 +387,46 @@ int mbedtls_ecdh_read_public( mbedtls_ecdh_context *ctx, * For more information, see mbedtls_ecp_mul(). * * \see ecp.h - * - * \param ctx The ECDH context. - * \param olen The number of Bytes written. - * \param buf The destination buffer. - * \param blen The length of the destination buffer. - * \param f_rng The RNG function. - * \param p_rng The RNG context. + + * \param ctx The ECDH context to use. This must be initialized + * and have its own private key generated and the peer's + * public key imported. + * \param olen The address at which to store the total number of + * Bytes written on success. This must not be \c NULL. + * \param buf The buffer to write the generated shared key to. This + * must be a writable buffer of size \p blen Bytes. + * \param blen The length of the destination buffer \p buf in Bytes. + * \param f_rng The RNG function, for blinding purposes. This may + * b \c NULL if blinding isn't needed. + * \param p_rng The RNG context. This may be \c NULL if \p f_rng + * doesn't need a context argument. * * \return \c 0 on success. - * \return An \c MBEDTLS_ERR_ECP_XXX error code on failure. + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + * \return Another \c MBEDTLS_ERR_ECP_XXX error code on failure. */ int mbedtls_ecdh_calc_secret( mbedtls_ecdh_context *ctx, size_t *olen, unsigned char *buf, size_t blen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); +#if defined(MBEDTLS_ECP_RESTARTABLE) +/** + * \brief This function enables restartable EC computations for this + * context. (Default: disabled.) + * + * \see \c mbedtls_ecp_set_max_ops() + * + * \note It is not possible to safely disable restartable + * computations once enabled, except by free-ing the context, + * which cancels possible in-progress operations. + * + * \param ctx The ECDH context to use. This must be initialized. + */ +void mbedtls_ecdh_enable_restart( mbedtls_ecdh_context *ctx ); +#endif /* MBEDTLS_ECP_RESTARTABLE */ + #ifdef __cplusplus } #endif diff --git a/thirdparty/mbedtls/include/mbedtls/ecdsa.h b/thirdparty/mbedtls/include/mbedtls/ecdsa.h index ce1a03d791..40fdab3729 100644 --- a/thirdparty/mbedtls/include/mbedtls/ecdsa.h +++ b/thirdparty/mbedtls/include/mbedtls/ecdsa.h @@ -55,20 +55,71 @@ /** The maximal size of an ECDSA signature in Bytes. */ #define MBEDTLS_ECDSA_MAX_LEN ( 3 + 2 * ( 3 + MBEDTLS_ECP_MAX_BYTES ) ) +#ifdef __cplusplus +extern "C" { +#endif + /** * \brief The ECDSA context structure. + * + * \warning Performing multiple operations concurrently on the same + * ECDSA context is not supported; objects of this type + * should not be shared between multiple threads. */ typedef mbedtls_ecp_keypair mbedtls_ecdsa_context; -#ifdef __cplusplus -extern "C" { +#if defined(MBEDTLS_ECP_RESTARTABLE) + +/** + * \brief Internal restart context for ecdsa_verify() + * + * \note Opaque struct, defined in ecdsa.c + */ +typedef struct mbedtls_ecdsa_restart_ver mbedtls_ecdsa_restart_ver_ctx; + +/** + * \brief Internal restart context for ecdsa_sign() + * + * \note Opaque struct, defined in ecdsa.c + */ +typedef struct mbedtls_ecdsa_restart_sig mbedtls_ecdsa_restart_sig_ctx; + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) +/** + * \brief Internal restart context for ecdsa_sign_det() + * + * \note Opaque struct, defined in ecdsa.c + */ +typedef struct mbedtls_ecdsa_restart_det mbedtls_ecdsa_restart_det_ctx; +#endif + +/** + * \brief General context for resuming ECDSA operations + */ +typedef struct +{ + mbedtls_ecp_restart_ctx ecp; /*!< base context for ECP restart and + shared administrative info */ + mbedtls_ecdsa_restart_ver_ctx *ver; /*!< ecdsa_verify() sub-context */ + mbedtls_ecdsa_restart_sig_ctx *sig; /*!< ecdsa_sign() sub-context */ +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) + mbedtls_ecdsa_restart_det_ctx *det; /*!< ecdsa_sign_det() sub-context */ #endif +} mbedtls_ecdsa_restart_ctx; + +#else /* MBEDTLS_ECP_RESTARTABLE */ + +/* Now we can declare functions that take a pointer to that */ +typedef void mbedtls_ecdsa_restart_ctx; + +#endif /* MBEDTLS_ECP_RESTARTABLE */ /** * \brief This function computes the ECDSA signature of a * previously-hashed message. * - * \note The deterministic version is usually preferred. + * \note The deterministic version implemented in + * mbedtls_ecdsa_sign_det() is usually preferred. * * \note If the bitlength of the message hash is larger than the * bitlength of the group order, then the hash is truncated @@ -78,14 +129,22 @@ extern "C" { * * \see ecp.h * - * \param grp The ECP group. - * \param r The first output integer. - * \param s The second output integer. - * \param d The private signing key. - * \param buf The message hash. - * \param blen The length of \p buf. - * \param f_rng The RNG function. - * \param p_rng The RNG context. + * \param grp The context for the elliptic curve to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param r The MPI context in which to store the first part + * the signature. This must be initialized. + * \param s The MPI context in which to store the second part + * the signature. This must be initialized. + * \param d The private signing key. This must be initialized. + * \param buf The content to be signed. This is usually the hash of + * the original data to be signed. This must be a readable + * buffer of length \p blen Bytes. It may be \c NULL if + * \p blen is zero. + * \param blen The length of \p buf in Bytes. + * \param f_rng The RNG function. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng doesn't need a context parameter. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_ECP_XXX @@ -112,21 +171,29 @@ int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, * * \see ecp.h * - * \param grp The ECP group. - * \param r The first output integer. - * \param s The second output integer. - * \param d The private signing key. - * \param buf The message hash. - * \param blen The length of \p buf. - * \param md_alg The MD algorithm used to hash the message. + * \param grp The context for the elliptic curve to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param r The MPI context in which to store the first part + * the signature. This must be initialized. + * \param s The MPI context in which to store the second part + * the signature. This must be initialized. + * \param d The private signing key. This must be initialized + * and setup, for example through mbedtls_ecp_gen_privkey(). + * \param buf The hashed content to be signed. This must be a readable + * buffer of length \p blen Bytes. It may be \c NULL if + * \p blen is zero. + * \param blen The length of \p buf in Bytes. + * \param md_alg The hash algorithm used to hash the original data. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX * error code on failure. */ -int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, - const mbedtls_mpi *d, const unsigned char *buf, size_t blen, - mbedtls_md_type_t md_alg ); +int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, + mbedtls_mpi *s, const mbedtls_mpi *d, + const unsigned char *buf, size_t blen, + mbedtls_md_type_t md_alg ); #endif /* MBEDTLS_ECDSA_DETERMINISTIC */ /** @@ -141,12 +208,19 @@ int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi * * \see ecp.h * - * \param grp The ECP group. - * \param buf The message hash. - * \param blen The length of \p buf. - * \param Q The public key to use for verification. + * \param grp The ECP group to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param buf The hashed content that was signed. This must be a readable + * buffer of length \p blen Bytes. It may be \c NULL if + * \p blen is zero. + * \param blen The length of \p buf in Bytes. + * \param Q The public key to use for verification. This must be + * initialized and setup. * \param r The first integer of the signature. + * This must be initialized. * \param s The second integer of the signature. + * This must be initialized. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the signature @@ -155,8 +229,9 @@ int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi * error code on failure for any other reason. */ int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp, - const unsigned char *buf, size_t blen, - const mbedtls_ecp_point *Q, const mbedtls_mpi *r, const mbedtls_mpi *s); + const unsigned char *buf, size_t blen, + const mbedtls_ecp_point *Q, const mbedtls_mpi *r, + const mbedtls_mpi *s); /** * \brief This function computes the ECDSA signature and writes it @@ -173,11 +248,6 @@ int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp, * of the Digital Signature Algorithm (DSA) and Elliptic * Curve Digital Signature Algorithm (ECDSA)</em>. * - * \note The \p sig buffer must be at least twice as large as the - * size of the curve used, plus 9. For example, 73 Bytes if - * a 256-bit curve is used. A buffer length of - * #MBEDTLS_ECDSA_MAX_LEN is always safe. - * * \note If the bitlength of the message hash is larger than the * bitlength of the group order, then the hash is truncated as * defined in <em>Standards for Efficient Cryptography Group @@ -186,25 +256,84 @@ int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp, * * \see ecp.h * - * \param ctx The ECDSA context. + * \param ctx The ECDSA context to use. This must be initialized + * and have a group and private key bound to it, for example + * via mbedtls_ecdsa_genkey() or mbedtls_ecdsa_from_keypair(). * \param md_alg The message digest that was used to hash the message. - * \param hash The message hash. - * \param hlen The length of the hash. - * \param sig The buffer that holds the signature. - * \param slen The length of the signature written. - * \param f_rng The RNG function. - * \param p_rng The RNG context. + * \param hash The message hash to be signed. This must be a readable + * buffer of length \p blen Bytes. + * \param hlen The length of the hash \p hash in Bytes. + * \param sig The buffer to which to write the signature. This must be a + * writable buffer of length at least twice as large as the + * size of the curve used, plus 9. For example, 73 Bytes if + * a 256-bit curve is used. A buffer length of + * #MBEDTLS_ECDSA_MAX_LEN is always safe. + * \param slen The address at which to store the actual length of + * the signature written. Must not be \c NULL. + * \param f_rng The RNG function. This must not be \c NULL if + * #MBEDTLS_ECDSA_DETERMINISTIC is unset. Otherwise, + * it is unused and may be set to \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng is \c NULL or doesn't use a context. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_ECP_XXX, \c MBEDTLS_ERR_MPI_XXX or * \c MBEDTLS_ERR_ASN1_XXX error code on failure. */ -int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, mbedtls_md_type_t md_alg, +int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, + mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hlen, unsigned char *sig, size_t *slen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); +/** + * \brief This function computes the ECDSA signature and writes it + * to a buffer, in a restartable way. + * + * \see \c mbedtls_ecdsa_write_signature() + * + * \note This function is like \c mbedtls_ecdsa_write_signature() + * but it can return early and restart according to the limit + * set with \c mbedtls_ecp_set_max_ops() to reduce blocking. + * + * \param ctx The ECDSA context to use. This must be initialized + * and have a group and private key bound to it, for example + * via mbedtls_ecdsa_genkey() or mbedtls_ecdsa_from_keypair(). + * \param md_alg The message digest that was used to hash the message. + * \param hash The message hash to be signed. This must be a readable + * buffer of length \p blen Bytes. + * \param hlen The length of the hash \p hash in Bytes. + * \param sig The buffer to which to write the signature. This must be a + * writable buffer of length at least twice as large as the + * size of the curve used, plus 9. For example, 73 Bytes if + * a 256-bit curve is used. A buffer length of + * #MBEDTLS_ECDSA_MAX_LEN is always safe. + * \param slen The address at which to store the actual length of + * the signature written. Must not be \c NULL. + * \param f_rng The RNG function. This must not be \c NULL if + * #MBEDTLS_ECDSA_DETERMINISTIC is unset. Otherwise, + * it is unused and may be set to \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng is \c NULL or doesn't use a context. + * \param rs_ctx The restart context to use. This may be \c NULL to disable + * restarting. If it is not \c NULL, it must point to an + * initialized restart context. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + * \return Another \c MBEDTLS_ERR_ECP_XXX, \c MBEDTLS_ERR_MPI_XXX or + * \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_ecdsa_write_signature_restartable( mbedtls_ecdsa_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hlen, + unsigned char *sig, size_t *slen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_ecdsa_restart_ctx *rs_ctx ); + #if defined(MBEDTLS_ECDSA_DETERMINISTIC) #if ! defined(MBEDTLS_DEPRECATED_REMOVED) #if defined(MBEDTLS_DEPRECATED_WARNING) @@ -225,11 +354,6 @@ int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, mbedtls_md_type_t * \warning It is not thread-safe to use the same context in * multiple threads. * - * \note The \p sig buffer must be at least twice as large as the - * size of the curve used, plus 9. For example, 73 Bytes if a - * 256-bit curve is used. A buffer length of - * #MBEDTLS_ECDSA_MAX_LEN is always safe. - * * \note If the bitlength of the message hash is larger than the * bitlength of the group order, then the hash is truncated as * defined in <em>Standards for Efficient Cryptography Group @@ -241,12 +365,20 @@ int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, mbedtls_md_type_t * \deprecated Superseded by mbedtls_ecdsa_write_signature() in * Mbed TLS version 2.0 and later. * - * \param ctx The ECDSA context. - * \param hash The message hash. - * \param hlen The length of the hash. - * \param sig The buffer that holds the signature. - * \param slen The length of the signature written. - * \param md_alg The MD algorithm used to hash the message. + * \param ctx The ECDSA context to use. This must be initialized + * and have a group and private key bound to it, for example + * via mbedtls_ecdsa_genkey() or mbedtls_ecdsa_from_keypair(). + * \param hash The message hash to be signed. This must be a readable + * buffer of length \p blen Bytes. + * \param hlen The length of the hash \p hash in Bytes. + * \param sig The buffer to which to write the signature. This must be a + * writable buffer of length at least twice as large as the + * size of the curve used, plus 9. For example, 73 Bytes if + * a 256-bit curve is used. A buffer length of + * #MBEDTLS_ECDSA_MAX_LEN is always safe. + * \param slen The address at which to store the actual length of + * the signature written. Must not be \c NULL. + * \param md_alg The message digest that was used to hash the message. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_ECP_XXX, \c MBEDTLS_ERR_MPI_XXX or @@ -271,11 +403,14 @@ int mbedtls_ecdsa_write_signature_det( mbedtls_ecdsa_context *ctx, * * \see ecp.h * - * \param ctx The ECDSA context. - * \param hash The message hash. - * \param hlen The size of the hash. - * \param sig The signature to read and verify. - * \param slen The size of \p sig. + * \param ctx The ECDSA context to use. This must be initialized + * and have a group and public key bound to it. + * \param hash The message hash that was signed. This must be a readable + * buffer of length \p size Bytes. + * \param hlen The size of the hash \p hash. + * \param sig The signature to read and verify. This must be a readable + * buffer of length \p slen Bytes. + * \param slen The size of \p sig in Bytes. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if signature is invalid. @@ -289,15 +424,53 @@ int mbedtls_ecdsa_read_signature( mbedtls_ecdsa_context *ctx, const unsigned char *sig, size_t slen ); /** + * \brief This function reads and verifies an ECDSA signature, + * in a restartable way. + * + * \see \c mbedtls_ecdsa_read_signature() + * + * \note This function is like \c mbedtls_ecdsa_read_signature() + * but it can return early and restart according to the limit + * set with \c mbedtls_ecp_set_max_ops() to reduce blocking. + * + * \param ctx The ECDSA context to use. This must be initialized + * and have a group and public key bound to it. + * \param hash The message hash that was signed. This must be a readable + * buffer of length \p size Bytes. + * \param hlen The size of the hash \p hash. + * \param sig The signature to read and verify. This must be a readable + * buffer of length \p slen Bytes. + * \param slen The size of \p sig in Bytes. + * \param rs_ctx The restart context to use. This may be \c NULL to disable + * restarting. If it is not \c NULL, it must point to an + * initialized restart context. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if signature is invalid. + * \return #MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH if there is a valid + * signature in \p sig, but its length is less than \p siglen. + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + * \return Another \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_ERR_MPI_XXX + * error code on failure for any other reason. + */ +int mbedtls_ecdsa_read_signature_restartable( mbedtls_ecdsa_context *ctx, + const unsigned char *hash, size_t hlen, + const unsigned char *sig, size_t slen, + mbedtls_ecdsa_restart_ctx *rs_ctx ); + +/** * \brief This function generates an ECDSA keypair on the given curve. * * \see ecp.h * * \param ctx The ECDSA context to store the keypair in. + * This must be initialized. * \param gid The elliptic curve to use. One of the various * \c MBEDTLS_ECP_DP_XXX macros depending on configuration. - * \param f_rng The RNG function. - * \param p_rng The RNG context. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng doesn't need a context argument. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_ECP_XXX code on failure. @@ -306,32 +479,59 @@ int mbedtls_ecdsa_genkey( mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id gid, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); /** - * \brief This function sets an ECDSA context from an EC key pair. + * \brief This function sets up an ECDSA context from an EC key pair. * * \see ecp.h * - * \param ctx The ECDSA context to set. - * \param key The EC key to use. + * \param ctx The ECDSA context to setup. This must be initialized. + * \param key The EC key to use. This must be initialized and hold + * a private-public key pair or a public key. In the former + * case, the ECDSA context may be used for signature creation + * and verification after this call. In the latter case, it + * may be used for signature verification. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_ECP_XXX code on failure. */ -int mbedtls_ecdsa_from_keypair( mbedtls_ecdsa_context *ctx, const mbedtls_ecp_keypair *key ); +int mbedtls_ecdsa_from_keypair( mbedtls_ecdsa_context *ctx, + const mbedtls_ecp_keypair *key ); /** * \brief This function initializes an ECDSA context. * * \param ctx The ECDSA context to initialize. + * This must not be \c NULL. */ void mbedtls_ecdsa_init( mbedtls_ecdsa_context *ctx ); /** * \brief This function frees an ECDSA context. * - * \param ctx The ECDSA context to free. + * \param ctx The ECDSA context to free. This may be \c NULL, + * in which case this function does nothing. If it + * is not \c NULL, it must be initialized. */ void mbedtls_ecdsa_free( mbedtls_ecdsa_context *ctx ); +#if defined(MBEDTLS_ECP_RESTARTABLE) +/** + * \brief Initialize a restart context. + * + * \param ctx The restart context to initialize. + * This must not be \c NULL. + */ +void mbedtls_ecdsa_restart_init( mbedtls_ecdsa_restart_ctx *ctx ); + +/** + * \brief Free the components of a restart context. + * + * \param ctx The restart context to free. This may be \c NULL, + * in which case this function does nothing. If it + * is not \c NULL, it must be initialized. + */ +void mbedtls_ecdsa_restart_free( mbedtls_ecdsa_restart_ctx *ctx ); +#endif /* MBEDTLS_ECP_RESTARTABLE */ + #ifdef __cplusplus } #endif diff --git a/thirdparty/mbedtls/include/mbedtls/ecjpake.h b/thirdparty/mbedtls/include/mbedtls/ecjpake.h index cc2b316f5e..b967af8385 100644 --- a/thirdparty/mbedtls/include/mbedtls/ecjpake.h +++ b/thirdparty/mbedtls/include/mbedtls/ecjpake.h @@ -68,7 +68,7 @@ typedef enum { * convetion from the Thread v1.0 spec. Correspondance is indicated in the * description as a pair C: client name, S: server name */ -typedef struct +typedef struct mbedtls_ecjpake_context { const mbedtls_md_info_t *md_info; /**< Hash to use */ mbedtls_ecp_group grp; /**< Elliptic curve */ @@ -92,28 +92,33 @@ typedef struct #endif /* MBEDTLS_ECJPAKE_ALT */ /** - * \brief Initialize a context - * (just makes it ready for setup() or free()). + * \brief Initialize an ECJPAKE context. * - * \param ctx context to initialize + * \param ctx The ECJPAKE context to initialize. + * This must not be \c NULL. */ void mbedtls_ecjpake_init( mbedtls_ecjpake_context *ctx ); /** - * \brief Set up a context for use + * \brief Set up an ECJPAKE context for use. * * \note Currently the only values for hash/curve allowed by the - * standard are MBEDTLS_MD_SHA256/MBEDTLS_ECP_DP_SECP256R1. + * standard are #MBEDTLS_MD_SHA256/#MBEDTLS_ECP_DP_SECP256R1. * - * \param ctx context to set up - * \param role Our role: client or server - * \param hash hash function to use (MBEDTLS_MD_XXX) - * \param curve elliptic curve identifier (MBEDTLS_ECP_DP_XXX) - * \param secret pre-shared secret (passphrase) - * \param len length of the shared secret + * \param ctx The ECJPAKE context to set up. This must be initialized. + * \param role The role of the caller. This must be either + * #MBEDTLS_ECJPAKE_CLIENT or #MBEDTLS_ECJPAKE_SERVER. + * \param hash The identifier of the hash function to use, + * for example #MBEDTLS_MD_SHA256. + * \param curve The identifier of the elliptic curve to use, + * for example #MBEDTLS_ECP_DP_SECP256R1. + * \param secret The pre-shared secret (passphrase). This must be + * a readable buffer of length \p len Bytes. It need + * only be valid for the duration of this call. + * \param len The length of the pre-shared secret \p secret. * - * \return 0 if successfull, - * a negative error code otherwise + * \return \c 0 if successful. + * \return A negative error code on failure. */ int mbedtls_ecjpake_setup( mbedtls_ecjpake_context *ctx, mbedtls_ecjpake_role role, @@ -123,29 +128,34 @@ int mbedtls_ecjpake_setup( mbedtls_ecjpake_context *ctx, size_t len ); /** - * \brief Check if a context is ready for use + * \brief Check if an ECJPAKE context is ready for use. * - * \param ctx Context to check + * \param ctx The ECJPAKE context to check. This must be + * initialized. * - * \return 0 if the context is ready for use, - * MBEDTLS_ERR_ECP_BAD_INPUT_DATA otherwise + * \return \c 0 if the context is ready for use. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA otherwise. */ int mbedtls_ecjpake_check( const mbedtls_ecjpake_context *ctx ); /** * \brief Generate and write the first round message * (TLS: contents of the Client/ServerHello extension, - * excluding extension type and length bytes) + * excluding extension type and length bytes). * - * \param ctx Context to use - * \param buf Buffer to write the contents to - * \param len Buffer size - * \param olen Will be updated with the number of bytes written - * \param f_rng RNG function - * \param p_rng RNG parameter + * \param ctx The ECJPAKE context to use. This must be + * initialized and set up. + * \param buf The buffer to write the contents to. This must be a + * writable buffer of length \p len Bytes. + * \param len The length of \p buf in Bytes. + * \param olen The address at which to store the total number + * of Bytes written to \p buf. This must not be \c NULL. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. This + * may be \c NULL if \p f_rng doesn't use a context. * - * \return 0 if successfull, - * a negative error code otherwise + * \return \c 0 if successful. + * \return A negative error code on failure. */ int mbedtls_ecjpake_write_round_one( mbedtls_ecjpake_context *ctx, unsigned char *buf, size_t len, size_t *olen, @@ -155,14 +165,16 @@ int mbedtls_ecjpake_write_round_one( mbedtls_ecjpake_context *ctx, /** * \brief Read and process the first round message * (TLS: contents of the Client/ServerHello extension, - * excluding extension type and length bytes) + * excluding extension type and length bytes). * - * \param ctx Context to use - * \param buf Pointer to extension contents - * \param len Extension length + * \param ctx The ECJPAKE context to use. This must be initialized + * and set up. + * \param buf The buffer holding the first round message. This must + * be a readable buffer of length \p len Bytes. + * \param len The length in Bytes of \p buf. * - * \return 0 if successfull, - * a negative error code otherwise + * \return \c 0 if successful. + * \return A negative error code on failure. */ int mbedtls_ecjpake_read_round_one( mbedtls_ecjpake_context *ctx, const unsigned char *buf, @@ -170,17 +182,21 @@ int mbedtls_ecjpake_read_round_one( mbedtls_ecjpake_context *ctx, /** * \brief Generate and write the second round message - * (TLS: contents of the Client/ServerKeyExchange) + * (TLS: contents of the Client/ServerKeyExchange). * - * \param ctx Context to use - * \param buf Buffer to write the contents to - * \param len Buffer size - * \param olen Will be updated with the number of bytes written - * \param f_rng RNG function - * \param p_rng RNG parameter + * \param ctx The ECJPAKE context to use. This must be initialized, + * set up, and already have performed round one. + * \param buf The buffer to write the round two contents to. + * This must be a writable buffer of length \p len Bytes. + * \param len The size of \p buf in Bytes. + * \param olen The address at which to store the total number of Bytes + * written to \p buf. This must not be \c NULL. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. This + * may be \c NULL if \p f_rng doesn't use a context. * - * \return 0 if successfull, - * a negative error code otherwise + * \return \c 0 if successful. + * \return A negative error code on failure. */ int mbedtls_ecjpake_write_round_two( mbedtls_ecjpake_context *ctx, unsigned char *buf, size_t len, size_t *olen, @@ -189,14 +205,16 @@ int mbedtls_ecjpake_write_round_two( mbedtls_ecjpake_context *ctx, /** * \brief Read and process the second round message - * (TLS: contents of the Client/ServerKeyExchange) + * (TLS: contents of the Client/ServerKeyExchange). * - * \param ctx Context to use - * \param buf Pointer to the message - * \param len Message length + * \param ctx The ECJPAKE context to use. This must be initialized + * and set up and already have performed round one. + * \param buf The buffer holding the second round message. This must + * be a readable buffer of length \p len Bytes. + * \param len The length in Bytes of \p buf. * - * \return 0 if successfull, - * a negative error code otherwise + * \return \c 0 if successful. + * \return A negative error code on failure. */ int mbedtls_ecjpake_read_round_two( mbedtls_ecjpake_context *ctx, const unsigned char *buf, @@ -204,17 +222,21 @@ int mbedtls_ecjpake_read_round_two( mbedtls_ecjpake_context *ctx, /** * \brief Derive the shared secret - * (TLS: Pre-Master Secret) + * (TLS: Pre-Master Secret). * - * \param ctx Context to use - * \param buf Buffer to write the contents to - * \param len Buffer size - * \param olen Will be updated with the number of bytes written - * \param f_rng RNG function - * \param p_rng RNG parameter + * \param ctx The ECJPAKE context to use. This must be initialized, + * set up and have performed both round one and two. + * \param buf The buffer to write the derived secret to. This must + * be a writable buffer of length \p len Bytes. + * \param len The length of \p buf in Bytes. + * \param olen The address at which to store the total number of Bytes + * written to \p buf. This must not be \c NULL. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. This + * may be \c NULL if \p f_rng doesn't use a context. * - * \return 0 if successfull, - * a negative error code otherwise + * \return \c 0 if successful. + * \return A negative error code on failure. */ int mbedtls_ecjpake_derive_secret( mbedtls_ecjpake_context *ctx, unsigned char *buf, size_t len, size_t *olen, @@ -222,14 +244,15 @@ int mbedtls_ecjpake_derive_secret( mbedtls_ecjpake_context *ctx, void *p_rng ); /** - * \brief Free a context's content + * \brief This clears an ECJPAKE context and frees any + * embedded data structure. * - * \param ctx context to free + * \param ctx The ECJPAKE context to free. This may be \c NULL, + * in which case this function does nothing. If it is not + * \c NULL, it must point to an initialized ECJPAKE context. */ void mbedtls_ecjpake_free( mbedtls_ecjpake_context *ctx ); - - #if defined(MBEDTLS_SELF_TEST) /** diff --git a/thirdparty/mbedtls/include/mbedtls/ecp.h b/thirdparty/mbedtls/include/mbedtls/ecp.h index 3a407986dd..de3a343cb6 100644 --- a/thirdparty/mbedtls/include/mbedtls/ecp.h +++ b/thirdparty/mbedtls/include/mbedtls/ecp.h @@ -49,8 +49,12 @@ #define MBEDTLS_ERR_ECP_RANDOM_FAILED -0x4D00 /**< Generation of random value, such as ephemeral key, failed. */ #define MBEDTLS_ERR_ECP_INVALID_KEY -0x4C80 /**< Invalid private or public key. */ #define MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH -0x4C00 /**< The buffer contains a valid signature followed by more data. */ + +/* MBEDTLS_ERR_ECP_HW_ACCEL_FAILED is deprecated and should not be used. */ #define MBEDTLS_ERR_ECP_HW_ACCEL_FAILED -0x4B80 /**< The ECP hardware accelerator failed. */ +#define MBEDTLS_ERR_ECP_IN_PROGRESS -0x4B00 /**< Operation in progress, call again with the same parameters to continue. */ + #ifdef __cplusplus extern "C" { #endif @@ -92,7 +96,7 @@ typedef enum /** * Curve information, for use by other modules. */ -typedef struct +typedef struct mbedtls_ecp_curve_info { mbedtls_ecp_group_id grp_id; /*!< An internal identifier. */ uint16_t tls_id; /*!< The TLS NamedCurve identifier. */ @@ -111,7 +115,7 @@ typedef struct * Otherwise, \p X and \p Y are its standard (affine) * coordinates. */ -typedef struct +typedef struct mbedtls_ecp_point { mbedtls_mpi X; /*!< The X coordinate of the ECP point. */ mbedtls_mpi Y; /*!< The Y coordinate of the ECP point. */ @@ -155,8 +159,12 @@ mbedtls_ecp_point; * additions or subtractions. Therefore, it is only an approximative modular * reduction. It must return 0 on success and non-zero on failure. * + * \note Alternative implementations must keep the group IDs distinct. If + * two group structures have the same ID, then they must be + * identical. + * */ -typedef struct +typedef struct mbedtls_ecp_group { mbedtls_ecp_group_id id; /*!< An internal group identifier. */ mbedtls_mpi P; /*!< The prime modulus of the base field. */ @@ -181,6 +189,70 @@ typedef struct } mbedtls_ecp_group; +#if defined(MBEDTLS_ECP_RESTARTABLE) + +/** + * \brief Internal restart context for multiplication + * + * \note Opaque struct + */ +typedef struct mbedtls_ecp_restart_mul mbedtls_ecp_restart_mul_ctx; + +/** + * \brief Internal restart context for ecp_muladd() + * + * \note Opaque struct + */ +typedef struct mbedtls_ecp_restart_muladd mbedtls_ecp_restart_muladd_ctx; + +/** + * \brief General context for resuming ECC operations + */ +typedef struct +{ + unsigned ops_done; /*!< current ops count */ + unsigned depth; /*!< call depth (0 = top-level) */ + mbedtls_ecp_restart_mul_ctx *rsm; /*!< ecp_mul_comb() sub-context */ + mbedtls_ecp_restart_muladd_ctx *ma; /*!< ecp_muladd() sub-context */ +} mbedtls_ecp_restart_ctx; + +/* + * Operation counts for restartable functions + */ +#define MBEDTLS_ECP_OPS_CHK 3 /*!< basic ops count for ecp_check_pubkey() */ +#define MBEDTLS_ECP_OPS_DBL 8 /*!< basic ops count for ecp_double_jac() */ +#define MBEDTLS_ECP_OPS_ADD 11 /*!< basic ops count for see ecp_add_mixed() */ +#define MBEDTLS_ECP_OPS_INV 120 /*!< empirical equivalent for mpi_mod_inv() */ + +/** + * \brief Internal; for restartable functions in other modules. + * Check and update basic ops budget. + * + * \param grp Group structure + * \param rs_ctx Restart context + * \param ops Number of basic ops to do + * + * \return \c 0 if doing \p ops basic ops is still allowed, + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS otherwise. + */ +int mbedtls_ecp_check_budget( const mbedtls_ecp_group *grp, + mbedtls_ecp_restart_ctx *rs_ctx, + unsigned ops ); + +/* Utility macro for checking and updating ops budget */ +#define MBEDTLS_ECP_BUDGET( ops ) \ + MBEDTLS_MPI_CHK( mbedtls_ecp_check_budget( grp, rs_ctx, \ + (unsigned) (ops) ) ); + +#else /* MBEDTLS_ECP_RESTARTABLE */ + +#define MBEDTLS_ECP_BUDGET( ops ) /* no-op; for compatibility */ + +/* We want to declare restartable versions of existing functions anyway */ +typedef void mbedtls_ecp_restart_ctx; + +#endif /* MBEDTLS_ECP_RESTARTABLE */ + /** * \name SECTION: Module settings * @@ -251,7 +323,7 @@ mbedtls_ecp_group; * \note Members are deliberately in the same order as in the * ::mbedtls_ecdsa_context structure. */ -typedef struct +typedef struct mbedtls_ecp_keypair { mbedtls_ecp_group grp; /*!< Elliptic curve and base point */ mbedtls_mpi d; /*!< our secret value */ @@ -270,6 +342,75 @@ mbedtls_ecp_keypair; */ #define MBEDTLS_ECP_TLS_NAMED_CURVE 3 /**< The named_curve of ECCurveType. */ +#if defined(MBEDTLS_ECP_RESTARTABLE) +/** + * \brief Set the maximum number of basic operations done in a row. + * + * If more operations are needed to complete a computation, + * #MBEDTLS_ERR_ECP_IN_PROGRESS will be returned by the + * function performing the computation. It is then the + * caller's responsibility to either call again with the same + * parameters until it returns 0 or an error code; or to free + * the restart context if the operation is to be aborted. + * + * It is strictly required that all input parameters and the + * restart context be the same on successive calls for the + * same operation, but output parameters need not be the + * same; they must not be used until the function finally + * returns 0. + * + * This only applies to functions whose documentation + * mentions they may return #MBEDTLS_ERR_ECP_IN_PROGRESS (or + * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS for functions in the + * SSL module). For functions that accept a "restart context" + * argument, passing NULL disables restart and makes the + * function equivalent to the function with the same name + * with \c _restartable removed. For functions in the ECDH + * module, restart is disabled unless the function accepts + * an "ECDH context" argument and + * mbedtls_ecdh_enable_restart() was previously called on + * that context. For function in the SSL module, restart is + * only enabled for specific sides and key exchanges + * (currently only for clients and ECDHE-ECDSA). + * + * \param max_ops Maximum number of basic operations done in a row. + * Default: 0 (unlimited). + * Lower (non-zero) values mean ECC functions will block for + * a lesser maximum amount of time. + * + * \note A "basic operation" is defined as a rough equivalent of a + * multiplication in GF(p) for the NIST P-256 curve. + * As an indication, with default settings, a scalar + * multiplication (full run of \c mbedtls_ecp_mul()) is: + * - about 3300 basic operations for P-256 + * - about 9400 basic operations for P-384 + * + * \note Very low values are not always respected: sometimes + * functions need to block for a minimum number of + * operations, and will do so even if max_ops is set to a + * lower value. That minimum depends on the curve size, and + * can be made lower by decreasing the value of + * \c MBEDTLS_ECP_WINDOW_SIZE. As an indication, here is the + * lowest effective value for various curves and values of + * that parameter (w for short): + * w=6 w=5 w=4 w=3 w=2 + * P-256 208 208 160 136 124 + * P-384 682 416 320 272 248 + * P-521 1364 832 640 544 496 + * + * \note This setting is currently ignored by Curve25519. + */ +void mbedtls_ecp_set_max_ops( unsigned max_ops ); + +/** + * \brief Check if restart is enabled (max_ops != 0) + * + * \return \c 0 if \c max_ops == 0 (restart disabled) + * \return \c 1 otherwise (restart enabled) + */ +int mbedtls_ecp_restart_is_enabled( void ); +#endif /* MBEDTLS_ECP_RESTARTABLE */ + /** * \brief This function retrieves the information defined in * mbedtls_ecp_curve_info() for all supported curves in order @@ -356,25 +497,51 @@ void mbedtls_ecp_point_free( mbedtls_ecp_point *pt ); /** * \brief This function frees the components of an ECP group. - * \param grp The group to free. + * + * \param grp The group to free. This may be \c NULL, in which + * case this function returns immediately. If it is not + * \c NULL, it must point to an initialized ECP group. */ void mbedtls_ecp_group_free( mbedtls_ecp_group *grp ); /** * \brief This function frees the components of a key pair. - * \param key The key pair to free. + * + * \param key The key pair to free. This may be \c NULL, in which + * case this function returns immediately. If it is not + * \c NULL, it must point to an initialized ECP key pair. */ void mbedtls_ecp_keypair_free( mbedtls_ecp_keypair *key ); +#if defined(MBEDTLS_ECP_RESTARTABLE) +/** + * \brief Initialize a restart context. + * + * \param ctx The restart context to initialize. This must + * not be \c NULL. + */ +void mbedtls_ecp_restart_init( mbedtls_ecp_restart_ctx *ctx ); + +/** + * \brief Free the components of a restart context. + * + * \param ctx The restart context to free. This may be \c NULL, in which + * case this function returns immediately. If it is not + * \c NULL, it must point to an initialized restart context. + */ +void mbedtls_ecp_restart_free( mbedtls_ecp_restart_ctx *ctx ); +#endif /* MBEDTLS_ECP_RESTARTABLE */ + /** * \brief This function copies the contents of point \p Q into * point \p P. * - * \param P The destination point. - * \param Q The source point. + * \param P The destination point. This must be initialized. + * \param Q The source point. This must be initialized. * * \return \c 0 on success. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + * \return Another negative error code for other kinds of failure. */ int mbedtls_ecp_copy( mbedtls_ecp_point *P, const mbedtls_ecp_point *Q ); @@ -382,31 +549,35 @@ int mbedtls_ecp_copy( mbedtls_ecp_point *P, const mbedtls_ecp_point *Q ); * \brief This function copies the contents of group \p src into * group \p dst. * - * \param dst The destination group. - * \param src The source group. + * \param dst The destination group. This must be initialized. + * \param src The source group. This must be initialized. * * \return \c 0 on success. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + * \return Another negative error code on other kinds of failure. */ -int mbedtls_ecp_group_copy( mbedtls_ecp_group *dst, const mbedtls_ecp_group *src ); +int mbedtls_ecp_group_copy( mbedtls_ecp_group *dst, + const mbedtls_ecp_group *src ); /** - * \brief This function sets a point to zero. + * \brief This function sets a point to the point at infinity. * - * \param pt The point to set. + * \param pt The point to set. This must be initialized. * * \return \c 0 on success. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + * \return Another negative error code on other kinds of failure. */ int mbedtls_ecp_set_zero( mbedtls_ecp_point *pt ); /** - * \brief This function checks if a point is zero. + * \brief This function checks if a point is the point at infinity. * - * \param pt The point to test. + * \param pt The point to test. This must be initialized. * * \return \c 1 if the point is zero. * \return \c 0 if the point is non-zero. + * \return A negative error code on failure. */ int mbedtls_ecp_is_zero( mbedtls_ecp_point *pt ); @@ -416,8 +587,8 @@ int mbedtls_ecp_is_zero( mbedtls_ecp_point *pt ); * \note This assumes that the points are normalized. Otherwise, * they may compare as "not equal" even if they are. * - * \param P The first point to compare. - * \param Q The second point to compare. + * \param P The first point to compare. This must be initialized. + * \param Q The second point to compare. This must be initialized. * * \return \c 0 if the points are equal. * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the points are not equal. @@ -429,7 +600,7 @@ int mbedtls_ecp_point_cmp( const mbedtls_ecp_point *P, * \brief This function imports a non-zero point from two ASCII * strings. * - * \param P The destination point. + * \param P The destination point. This must be initialized. * \param radix The numeric base of the input. * \param x The first affine coordinate, as a null-terminated string. * \param y The second affine coordinate, as a null-terminated string. @@ -444,15 +615,21 @@ int mbedtls_ecp_point_read_string( mbedtls_ecp_point *P, int radix, * \brief This function exports a point into unsigned binary data. * * \param grp The group to which the point should belong. - * \param P The point to export. - * \param format The point format. Should be an \c MBEDTLS_ECP_PF_XXX macro. - * \param olen The length of the output. - * \param buf The output buffer. - * \param buflen The length of the output buffer. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param P The point to export. This must be initialized. + * \param format The point format. This must be either + * #MBEDTLS_ECP_PF_COMPRESSED or #MBEDTLS_ECP_PF_UNCOMPRESSED. + * \param olen The address at which to store the length of + * the output in Bytes. This must not be \c NULL. + * \param buf The output buffer. This must be a writable buffer + * of length \p buflen Bytes. + * \param buflen The length of the output buffer \p buf in Bytes. * * \return \c 0 on success. - * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA - * or #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL on failure. + * \return #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL if the output buffer + * is too small to hold the point. + * \return Another negative error code on other kinds of failure. */ int mbedtls_ecp_point_write_binary( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *P, int format, size_t *olen, @@ -466,108 +643,158 @@ int mbedtls_ecp_point_write_binary( const mbedtls_ecp_group *grp, const mbedtls_ * for that. * * \param grp The group to which the point should belong. - * \param P The point to import. - * \param buf The input buffer. - * \param ilen The length of the input. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param P The destination context to import the point to. + * This must be initialized. + * \param buf The input buffer. This must be a readable buffer + * of length \p ilen Bytes. + * \param ilen The length of the input buffer \p buf in Bytes. * * \return \c 0 on success. - * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the input is invalid. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the point format * is not implemented. - * */ -int mbedtls_ecp_point_read_binary( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P, - const unsigned char *buf, size_t ilen ); +int mbedtls_ecp_point_read_binary( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *P, + const unsigned char *buf, size_t ilen ); /** * \brief This function imports a point from a TLS ECPoint record. * - * \note On function return, \p buf is updated to point to immediately + * \note On function return, \p *buf is updated to point immediately * after the ECPoint record. * - * \param grp The ECP group used. + * \param grp The ECP group to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). * \param pt The destination point. * \param buf The address of the pointer to the start of the input buffer. * \param len The length of the buffer. * * \return \c 0 on success. - * \return An \c MBEDTLS_ERR_MPI_XXX error code on initialization failure. + * \return An \c MBEDTLS_ERR_MPI_XXX error code on initialization + * failure. * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid. */ -int mbedtls_ecp_tls_read_point( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt, - const unsigned char **buf, size_t len ); +int mbedtls_ecp_tls_read_point( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *pt, + const unsigned char **buf, size_t len ); /** - * \brief This function exports a point as a TLS ECPoint record. - * - * \param grp The ECP group used. - * \param pt The point format to export to. The point format is an - * \c MBEDTLS_ECP_PF_XXX constant. - * \param format The export format. - * \param olen The length of the data written. - * \param buf The buffer to write to. - * \param blen The length of the buffer. + * \brief This function exports a point as a TLS ECPoint record + * defined in RFC 4492, Section 5.4. + * + * \param grp The ECP group to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param pt The point to be exported. This must be initialized. + * \param format The point format to use. This must be either + * #MBEDTLS_ECP_PF_COMPRESSED or #MBEDTLS_ECP_PF_UNCOMPRESSED. + * \param olen The address at which to store the length in Bytes + * of the data written. + * \param buf The target buffer. This must be a writable buffer of + * length \p blen Bytes. + * \param blen The length of the target buffer \p buf in Bytes. * * \return \c 0 on success. - * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA or - * #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL on failure. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the input is invalid. + * \return #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL if the target buffer + * is too small to hold the exported point. + * \return Another negative error code on other kinds of failure. */ -int mbedtls_ecp_tls_write_point( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt, - int format, size_t *olen, - unsigned char *buf, size_t blen ); +int mbedtls_ecp_tls_write_point( const mbedtls_ecp_group *grp, + const mbedtls_ecp_point *pt, + int format, size_t *olen, + unsigned char *buf, size_t blen ); /** - * \brief This function sets a group using standardized domain parameters. + * \brief This function sets up an ECP group context + * from a standardized set of domain parameters. * * \note The index should be a value of the NamedCurve enum, * as defined in <em>RFC-4492: Elliptic Curve Cryptography * (ECC) Cipher Suites for Transport Layer Security (TLS)</em>, * usually in the form of an \c MBEDTLS_ECP_DP_XXX macro. * - * \param grp The destination group. + * \param grp The group context to setup. This must be initialized. * \param id The identifier of the domain parameter set to load. * - * \return \c 0 on success, - * \return An \c MBEDTLS_ERR_MPI_XXX error code on initialization failure. - * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE for unkownn groups. - + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if \p id doesn't + * correspond to a known group. + * \return Another negative error code on other kinds of failure. */ int mbedtls_ecp_group_load( mbedtls_ecp_group *grp, mbedtls_ecp_group_id id ); /** - * \brief This function sets a group from a TLS ECParameters record. + * \brief This function sets up an ECP group context from a TLS + * ECParameters record as defined in RFC 4492, Section 5.4. * - * \note \p buf is updated to point right after the ECParameters record - * on exit. + * \note The read pointer \p buf is updated to point right after + * the ECParameters record on exit. * - * \param grp The destination group. + * \param grp The group context to setup. This must be initialized. * \param buf The address of the pointer to the start of the input buffer. - * \param len The length of the buffer. + * \param len The length of the input buffer \c *buf in Bytes. * * \return \c 0 on success. - * \return An \c MBEDTLS_ERR_MPI_XXX error code on initialization failure. * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid. + * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the group is not + * recognized. + * \return Another negative error code on other kinds of failure. */ -int mbedtls_ecp_tls_read_group( mbedtls_ecp_group *grp, const unsigned char **buf, size_t len ); +int mbedtls_ecp_tls_read_group( mbedtls_ecp_group *grp, + const unsigned char **buf, size_t len ); /** - * \brief This function writes the TLS ECParameters record for a group. + * \brief This function extracts an elliptic curve group ID from a + * TLS ECParameters record as defined in RFC 4492, Section 5.4. + * + * \note The read pointer \p buf is updated to point right after + * the ECParameters record on exit. + * + * \param grp The address at which to store the group id. + * This must not be \c NULL. + * \param buf The address of the pointer to the start of the input buffer. + * \param len The length of the input buffer \c *buf in Bytes. * - * \param grp The ECP group used. - * \param olen The number of Bytes written. - * \param buf The buffer to write to. - * \param blen The length of the buffer. + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid. + * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the group is not + * recognized. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_tls_read_group_id( mbedtls_ecp_group_id *grp, + const unsigned char **buf, + size_t len ); +/** + * \brief This function exports an elliptic curve as a TLS + * ECParameters record as defined in RFC 4492, Section 5.4. + * + * \param grp The ECP group to be exported. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param olen The address at which to store the number of Bytes written. + * This must not be \c NULL. + * \param buf The buffer to write to. This must be a writable buffer + * of length \p blen Bytes. + * \param blen The length of the output buffer \p buf in Bytes. * * \return \c 0 on success. - * \return #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL on failure. + * \return #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL if the output + * buffer is too small to hold the exported group. + * \return Another negative error code on other kinds of failure. */ -int mbedtls_ecp_tls_write_group( const mbedtls_ecp_group *grp, size_t *olen, - unsigned char *buf, size_t blen ); +int mbedtls_ecp_tls_write_group( const mbedtls_ecp_group *grp, + size_t *olen, + unsigned char *buf, size_t blen ); /** - * \brief This function performs multiplication of a point by - * an integer: \p R = \p m * \p P. + * \brief This function performs a scalar multiplication of a point + * by an integer: \p R = \p m * \p P. * * It is not thread-safe to use same group in multiple threads. * @@ -581,23 +808,63 @@ int mbedtls_ecp_tls_write_group( const mbedtls_ecp_group *grp, size_t *olen, * targeting these results. We recommend always providing * a non-NULL \p f_rng. The overhead is negligible. * - * \param grp The ECP group. - * \param R The destination point. - * \param m The integer by which to multiply. - * \param P The point to multiply. - * \param f_rng The RNG function. - * \param p_rng The RNG context. + * \param grp The ECP group to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param R The point in which to store the result of the calculation. + * This must be initialized. + * \param m The integer by which to multiply. This must be initialized. + * \param P The point to multiply. This must be initialized. + * \param f_rng The RNG function. This may be \c NULL if randomization + * of intermediate results isn't desired (discouraged). + * \param p_rng The RNG context to be passed to \p p_rng. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_INVALID_KEY if \p m is not a valid private * key, or \p P is not a valid public key. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + * \return Another negative error code on other kinds of failure. */ int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, const mbedtls_ecp_point *P, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); /** + * \brief This function performs multiplication of a point by + * an integer: \p R = \p m * \p P in a restartable way. + * + * \see mbedtls_ecp_mul() + * + * \note This function does the same as \c mbedtls_ecp_mul(), but + * it can return early and restart according to the limit set + * with \c mbedtls_ecp_set_max_ops() to reduce blocking. + * + * \param grp The ECP group to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param R The point in which to store the result of the calculation. + * This must be initialized. + * \param m The integer by which to multiply. This must be initialized. + * \param P The point to multiply. This must be initialized. + * \param f_rng The RNG function. This may be \c NULL if randomization + * of intermediate results isn't desired (discouraged). + * \param p_rng The RNG context to be passed to \p p_rng. + * \param rs_ctx The restart context (NULL disables restart). + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_INVALID_KEY if \p m is not a valid private + * key, or \p P is not a valid public key. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_mul_restartable( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + mbedtls_ecp_restart_ctx *rs_ctx ); + +/** * \brief This function performs multiplication and addition of two * points by integers: \p R = \p m * \p P + \p n * \p Q * @@ -606,24 +873,71 @@ int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, * \note In contrast to mbedtls_ecp_mul(), this function does not * guarantee a constant execution flow and timing. * - * \param grp The ECP group. - * \param R The destination point. + * \param grp The ECP group to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param R The point in which to store the result of the calculation. + * This must be initialized. * \param m The integer by which to multiply \p P. - * \param P The point to multiply by \p m. + * This must be initialized. + * \param P The point to multiply by \p m. This must be initialized. * \param n The integer by which to multiply \p Q. + * This must be initialized. * \param Q The point to be multiplied by \p n. + * This must be initialized. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_INVALID_KEY if \p m or \p n are not * valid private keys, or \p P or \p Q are not valid public * keys. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + * \return Another negative error code on other kinds of failure. */ int mbedtls_ecp_muladd( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, const mbedtls_ecp_point *P, const mbedtls_mpi *n, const mbedtls_ecp_point *Q ); /** + * \brief This function performs multiplication and addition of two + * points by integers: \p R = \p m * \p P + \p n * \p Q in a + * restartable way. + * + * \see \c mbedtls_ecp_muladd() + * + * \note This function works the same as \c mbedtls_ecp_muladd(), + * but it can return early and restart according to the limit + * set with \c mbedtls_ecp_set_max_ops() to reduce blocking. + * + * \param grp The ECP group to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param R The point in which to store the result of the calculation. + * This must be initialized. + * \param m The integer by which to multiply \p P. + * This must be initialized. + * \param P The point to multiply by \p m. This must be initialized. + * \param n The integer by which to multiply \p Q. + * This must be initialized. + * \param Q The point to be multiplied by \p n. + * This must be initialized. + * \param rs_ctx The restart context (NULL disables restart). + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_INVALID_KEY if \p m or \p n are not + * valid private keys, or \p P or \p Q are not valid public + * keys. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_muladd_restartable( + mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + const mbedtls_mpi *n, const mbedtls_ecp_point *Q, + mbedtls_ecp_restart_ctx *rs_ctx ); + +/** * \brief This function checks that a point is a valid public key * on this curve. * @@ -640,30 +954,60 @@ int mbedtls_ecp_muladd( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, * structures, such as ::mbedtls_ecdh_context or * ::mbedtls_ecdsa_context. * - * \param grp The curve the point should lie on. - * \param pt The point to check. + * \param grp The ECP group the point should belong to. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param pt The point to check. This must be initialized. * * \return \c 0 if the point is a valid public key. - * \return #MBEDTLS_ERR_ECP_INVALID_KEY on failure. + * \return #MBEDTLS_ERR_ECP_INVALID_KEY if the point is not + * a valid public key for the given curve. + * \return Another negative error code on other kinds of failure. */ -int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt ); +int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp, + const mbedtls_ecp_point *pt ); /** - * \brief This function checks that an \p mbedtls_mpi is a valid private - * key for this curve. + * \brief This function checks that an \p mbedtls_mpi is a + * valid private key for this curve. * * \note This function uses bare components rather than an * ::mbedtls_ecp_keypair structure to ease use with other * structures, such as ::mbedtls_ecdh_context or * ::mbedtls_ecdsa_context. * - * \param grp The group used. - * \param d The integer to check. + * \param grp The ECP group the private key should belong to. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param d The integer to check. This must be initialized. * * \return \c 0 if the point is a valid private key. - * \return #MBEDTLS_ERR_ECP_INVALID_KEY on failure. + * \return #MBEDTLS_ERR_ECP_INVALID_KEY if the point is not a valid + * private key for the given curve. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, + const mbedtls_mpi *d ); + +/** + * \brief This function generates a private key. + * + * \param grp The ECP group to generate a private key for. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param d The destination MPI (secret part). This must be initialized. + * \param f_rng The RNG function. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. This may be + * \c NULL if \p f_rng doesn't need a context argument. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX error code + * on failure. */ -int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, const mbedtls_mpi *d ); +int mbedtls_ecp_gen_privkey( const mbedtls_ecp_group *grp, + mbedtls_mpi *d, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); /** * \brief This function generates a keypair with a configurable base @@ -674,22 +1018,29 @@ int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, const mbedtls_mpi * * structures, such as ::mbedtls_ecdh_context or * ::mbedtls_ecdsa_context. * - * \param grp The ECP group. - * \param G The chosen base point. + * \param grp The ECP group to generate a key pair for. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param G The base point to use. This must be initialized + * and belong to \p grp. It replaces the default base + * point \c grp->G used by mbedtls_ecp_gen_keypair(). * \param d The destination MPI (secret part). + * This must be initialized. * \param Q The destination point (public part). - * \param f_rng The RNG function. - * \param p_rng The RNG context. + * This must be initialized. + * \param f_rng The RNG function. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may + * be \c NULL if \p f_rng doesn't need a context argument. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX error code * on failure. */ int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp, - const mbedtls_ecp_point *G, - mbedtls_mpi *d, mbedtls_ecp_point *Q, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); + const mbedtls_ecp_point *G, + mbedtls_mpi *d, mbedtls_ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); /** * \brief This function generates an ECP keypair. @@ -699,34 +1050,42 @@ int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp, * structures, such as ::mbedtls_ecdh_context or * ::mbedtls_ecdsa_context. * - * \param grp The ECP group. + * \param grp The ECP group to generate a key pair for. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). * \param d The destination MPI (secret part). + * This must be initialized. * \param Q The destination point (public part). - * \param f_rng The RNG function. - * \param p_rng The RNG context. + * This must be initialized. + * \param f_rng The RNG function. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may + * be \c NULL if \p f_rng doesn't need a context argument. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX error code * on failure. */ -int mbedtls_ecp_gen_keypair( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); +int mbedtls_ecp_gen_keypair( mbedtls_ecp_group *grp, mbedtls_mpi *d, + mbedtls_ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); /** * \brief This function generates an ECP key. * * \param grp_id The ECP group identifier. - * \param key The destination key. - * \param f_rng The RNG function. - * \param p_rng The RNG context. + * \param key The destination key. This must be initialized. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may + * be \c NULL if \p f_rng doesn't need a context argument. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX error code * on failure. */ int mbedtls_ecp_gen_key( mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); /** * \brief This function checks that the keypair objects @@ -734,16 +1093,19 @@ int mbedtls_ecp_gen_key( mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key, * same public point, and that the private key in * \p prv is consistent with the public key. * - * \param pub The keypair structure holding the public key. - * If it contains a private key, that part is ignored. + * \param pub The keypair structure holding the public key. This + * must be initialized. If it contains a private key, that + * part is ignored. * \param prv The keypair structure holding the full keypair. + * This must be initialized. * * \return \c 0 on success, meaning that the keys are valid and match. * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the keys are invalid or do not match. * \return An \c MBEDTLS_ERR_ECP_XXX or an \c MBEDTLS_ERR_MPI_XXX * error code on calculation failure. */ -int mbedtls_ecp_check_pub_priv( const mbedtls_ecp_keypair *pub, const mbedtls_ecp_keypair *prv ); +int mbedtls_ecp_check_pub_priv( const mbedtls_ecp_keypair *pub, + const mbedtls_ecp_keypair *prv ); #if defined(MBEDTLS_SELF_TEST) diff --git a/thirdparty/mbedtls/include/mbedtls/entropy.h b/thirdparty/mbedtls/include/mbedtls/entropy.h index a5cb05a584..ca06dc3c58 100644 --- a/thirdparty/mbedtls/include/mbedtls/entropy.h +++ b/thirdparty/mbedtls/include/mbedtls/entropy.h @@ -107,7 +107,7 @@ typedef int (*mbedtls_entropy_f_source_ptr)(void *data, unsigned char *output, s /** * \brief Entropy source state */ -typedef struct +typedef struct mbedtls_entropy_source_state { mbedtls_entropy_f_source_ptr f_source; /**< The entropy source callback */ void * p_source; /**< The callback data pointer */ @@ -120,7 +120,7 @@ mbedtls_entropy_source_state; /** * \brief Entropy context structure */ -typedef struct +typedef struct mbedtls_entropy_context { int accumulator_started; #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) diff --git a/thirdparty/mbedtls/include/mbedtls/error.h b/thirdparty/mbedtls/include/mbedtls/error.h index 6b82d4fbbe..647a11a566 100644 --- a/thirdparty/mbedtls/include/mbedtls/error.h +++ b/thirdparty/mbedtls/include/mbedtls/error.h @@ -74,12 +74,13 @@ * MD4 1 0x002D-0x002D * MD5 1 0x002F-0x002F * RIPEMD160 1 0x0031-0x0031 - * SHA1 1 0x0035-0x0035 - * SHA256 1 0x0037-0x0037 - * SHA512 1 0x0039-0x0039 + * SHA1 1 0x0035-0x0035 0x0073-0x0073 + * SHA256 1 0x0037-0x0037 0x0074-0x0074 + * SHA512 1 0x0039-0x0039 0x0075-0x0075 * CHACHA20 3 0x0051-0x0055 * POLY1305 3 0x0057-0x005B * CHACHAPOLY 2 0x0054-0x0056 + * PLATFORM 1 0x0070-0x0072 * * High-level module nr (3 bits - 0x0...-0x7...) * Name ID Nr of Errors @@ -90,12 +91,12 @@ * DHM 3 11 * PK 3 15 (Started from top) * RSA 4 11 - * ECP 4 9 (Started from top) + * ECP 4 10 (Started from top) * MD 5 5 * HKDF 5 1 (Started from top) * CIPHER 6 8 - * SSL 6 22 (Started from top) - * SSL 7 31 + * SSL 6 23 (Started from top) + * SSL 7 32 * * Module dependent error code (5 bits 0x.00.-0x.F8.) */ diff --git a/thirdparty/mbedtls/include/mbedtls/gcm.h b/thirdparty/mbedtls/include/mbedtls/gcm.h index 87535ab957..fccabb0d97 100644 --- a/thirdparty/mbedtls/include/mbedtls/gcm.h +++ b/thirdparty/mbedtls/include/mbedtls/gcm.h @@ -41,7 +41,10 @@ #define MBEDTLS_GCM_DECRYPT 0 #define MBEDTLS_ERR_GCM_AUTH_FAILED -0x0012 /**< Authenticated decryption failed. */ + +/* MBEDTLS_ERR_GCM_HW_ACCEL_FAILED is deprecated and should not be used. */ #define MBEDTLS_ERR_GCM_HW_ACCEL_FAILED -0x0013 /**< GCM hardware accelerator failed. */ + #define MBEDTLS_ERR_GCM_BAD_INPUT -0x0014 /**< Bad input parameters to function. */ #ifdef __cplusplus @@ -53,7 +56,8 @@ extern "C" { /** * \brief The GCM context structure. */ -typedef struct { +typedef struct mbedtls_gcm_context +{ mbedtls_cipher_context_t cipher_ctx; /*!< The cipher context used. */ uint64_t HL[16]; /*!< Precalculated HTable low. */ uint64_t HH[16]; /*!< Precalculated HTable high. */ @@ -81,7 +85,7 @@ mbedtls_gcm_context; * cipher, nor set the key. For this purpose, use * mbedtls_gcm_setkey(). * - * \param ctx The GCM context to initialize. + * \param ctx The GCM context to initialize. This must not be \c NULL. */ void mbedtls_gcm_init( mbedtls_gcm_context *ctx ); @@ -89,9 +93,10 @@ void mbedtls_gcm_init( mbedtls_gcm_context *ctx ); * \brief This function associates a GCM context with a * cipher algorithm and a key. * - * \param ctx The GCM context to initialize. + * \param ctx The GCM context. This must be initialized. * \param cipher The 128-bit block cipher to use. - * \param key The encryption key. + * \param key The encryption key. This must be a readable buffer of at + * least \p keybits bits. * \param keybits The key size in bits. Valid options are: * <ul><li>128 bits</li> * <li>192 bits</li> @@ -118,7 +123,8 @@ int mbedtls_gcm_setkey( mbedtls_gcm_context *ctx, * authentic. You should use this function to perform encryption * only. For decryption, use mbedtls_gcm_auth_decrypt() instead. * - * \param ctx The GCM context to use for encryption or decryption. + * \param ctx The GCM context to use for encryption or decryption. This + * must be initialized. * \param mode The operation to perform: * - #MBEDTLS_GCM_ENCRYPT to perform authenticated encryption. * The ciphertext is written to \p output and the @@ -132,22 +138,28 @@ int mbedtls_gcm_setkey( mbedtls_gcm_context *ctx, * calling this function in decryption mode. * \param length The length of the input data, which is equal to the length * of the output data. - * \param iv The initialization vector. + * \param iv The initialization vector. This must be a readable buffer of + * at least \p iv_len Bytes. * \param iv_len The length of the IV. - * \param add The buffer holding the additional data. + * \param add The buffer holding the additional data. This must be of at + * least that size in Bytes. * \param add_len The length of the additional data. - * \param input The buffer holding the input data. Its size is \b length. - * \param output The buffer for holding the output data. It must have room - * for \b length bytes. + * \param input The buffer holding the input data. If \p length is greater + * than zero, this must be a readable buffer of at least that + * size in Bytes. + * \param output The buffer for holding the output data. If \p length is greater + * than zero, this must be a writable buffer of at least that + * size in Bytes. * \param tag_len The length of the tag to generate. - * \param tag The buffer for holding the tag. + * \param tag The buffer for holding the tag. This must be a readable + * buffer of at least \p tag_len Bytes. * * \return \c 0 if the encryption or decryption was performed * successfully. Note that in #MBEDTLS_GCM_DECRYPT mode, * this does not indicate that the data is authentic. - * \return #MBEDTLS_ERR_GCM_BAD_INPUT if the lengths are not valid. - * \return #MBEDTLS_ERR_GCM_HW_ACCEL_FAILED or a cipher-specific - * error code if the encryption or decryption failed. + * \return #MBEDTLS_ERR_GCM_BAD_INPUT if the lengths or pointers are + * not valid or a cipher-specific error code if the encryption + * or decryption failed. */ int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_context *ctx, int mode, @@ -169,24 +181,30 @@ int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_context *ctx, * input buffer. If the buffers overlap, the output buffer * must trail at least 8 Bytes behind the input buffer. * - * \param ctx The GCM context. + * \param ctx The GCM context. This must be initialized. * \param length The length of the ciphertext to decrypt, which is also * the length of the decrypted plaintext. - * \param iv The initialization vector. + * \param iv The initialization vector. This must be a readable buffer + * of at least \p iv_len Bytes. * \param iv_len The length of the IV. - * \param add The buffer holding the additional data. + * \param add The buffer holding the additional data. This must be of at + * least that size in Bytes. * \param add_len The length of the additional data. - * \param tag The buffer holding the tag to verify. + * \param tag The buffer holding the tag to verify. This must be a + * readable buffer of at least \p tag_len Bytes. * \param tag_len The length of the tag to verify. - * \param input The buffer holding the ciphertext. Its size is \b length. - * \param output The buffer for holding the decrypted plaintext. It must - * have room for \b length bytes. + * \param input The buffer holding the ciphertext. If \p length is greater + * than zero, this must be a readable buffer of at least that + * size. + * \param output The buffer for holding the decrypted plaintext. If \p length + * is greater than zero, this must be a writable buffer of at + * least that size. * * \return \c 0 if successful and authenticated. * \return #MBEDTLS_ERR_GCM_AUTH_FAILED if the tag does not match. - * \return #MBEDTLS_ERR_GCM_BAD_INPUT if the lengths are not valid. - * \return #MBEDTLS_ERR_GCM_HW_ACCEL_FAILED or a cipher-specific - * error code if the decryption failed. + * \return #MBEDTLS_ERR_GCM_BAD_INPUT if the lengths or pointers are + * not valid or a cipher-specific error code if the decryption + * failed. */ int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx, size_t length, @@ -203,15 +221,16 @@ int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx, * \brief This function starts a GCM encryption or decryption * operation. * - * \param ctx The GCM context. + * \param ctx The GCM context. This must be initialized. * \param mode The operation to perform: #MBEDTLS_GCM_ENCRYPT or * #MBEDTLS_GCM_DECRYPT. - * \param iv The initialization vector. + * \param iv The initialization vector. This must be a readable buffer of + * at least \p iv_len Bytes. * \param iv_len The length of the IV. - * \param add The buffer holding the additional data, or NULL - * if \p add_len is 0. - * \param add_len The length of the additional data. If 0, - * \p add is NULL. + * \param add The buffer holding the additional data, or \c NULL + * if \p add_len is \c 0. + * \param add_len The length of the additional data. If \c 0, + * \p add may be \c NULL. * * \return \c 0 on success. */ @@ -234,11 +253,15 @@ int mbedtls_gcm_starts( mbedtls_gcm_context *ctx, * input buffer. If the buffers overlap, the output buffer * must trail at least 8 Bytes behind the input buffer. * - * \param ctx The GCM context. + * \param ctx The GCM context. This must be initialized. * \param length The length of the input data. This must be a multiple of * 16 except in the last call before mbedtls_gcm_finish(). - * \param input The buffer holding the input data. - * \param output The buffer for holding the output data. + * \param input The buffer holding the input data. If \p length is greater + * than zero, this must be a readable buffer of at least that + * size in Bytes. + * \param output The buffer for holding the output data. If \p length is + * greater than zero, this must be a writable buffer of at + * least that size in Bytes. * * \return \c 0 on success. * \return #MBEDTLS_ERR_GCM_BAD_INPUT on failure. @@ -255,9 +278,11 @@ int mbedtls_gcm_update( mbedtls_gcm_context *ctx, * It wraps up the GCM stream, and generates the * tag. The tag can have a maximum length of 16 Bytes. * - * \param ctx The GCM context. - * \param tag The buffer for holding the tag. - * \param tag_len The length of the tag to generate. Must be at least four. + * \param ctx The GCM context. This must be initialized. + * \param tag The buffer for holding the tag. This must be a readable + * buffer of at least \p tag_len Bytes. + * \param tag_len The length of the tag to generate. This must be at least + * four. * * \return \c 0 on success. * \return #MBEDTLS_ERR_GCM_BAD_INPUT on failure. @@ -270,7 +295,8 @@ int mbedtls_gcm_finish( mbedtls_gcm_context *ctx, * \brief This function clears a GCM context and the underlying * cipher sub-context. * - * \param ctx The GCM context to clear. + * \param ctx The GCM context to clear. If this is \c NULL, the call has + * no effect. Otherwise, this must be initialized. */ void mbedtls_gcm_free( mbedtls_gcm_context *ctx ); diff --git a/thirdparty/mbedtls/include/mbedtls/havege.h b/thirdparty/mbedtls/include/mbedtls/havege.h index d4cb3ed38d..57e8c40943 100644 --- a/thirdparty/mbedtls/include/mbedtls/havege.h +++ b/thirdparty/mbedtls/include/mbedtls/havege.h @@ -35,7 +35,7 @@ extern "C" { /** * \brief HAVEGE state structure */ -typedef struct +typedef struct mbedtls_havege_state { int PT1, PT2, offset[2]; int pool[MBEDTLS_HAVEGE_COLLECT_SIZE]; diff --git a/thirdparty/mbedtls/include/mbedtls/hkdf.h b/thirdparty/mbedtls/include/mbedtls/hkdf.h index 6833e7272e..e6ed7cde97 100644 --- a/thirdparty/mbedtls/include/mbedtls/hkdf.h +++ b/thirdparty/mbedtls/include/mbedtls/hkdf.h @@ -73,6 +73,11 @@ int mbedtls_hkdf( const mbedtls_md_info_t *md, const unsigned char *salt, * \brief Take the input keying material \p ikm and extract from it a * fixed-length pseudorandom key \p prk. * + * \warning This function should only be used if the security of it has been + * studied and established in that particular context (eg. TLS 1.3 + * key schedule). For standard HKDF security guarantees use + * \c mbedtls_hkdf instead. + * * \param md A hash function; md.size denotes the length of the * hash function output in bytes. * \param salt An optional salt value (a non-secret random value); @@ -97,10 +102,15 @@ int mbedtls_hkdf_extract( const mbedtls_md_info_t *md, * \brief Expand the supplied \p prk into several additional pseudorandom * keys, which is the output of the HKDF. * + * \warning This function should only be used if the security of it has been + * studied and established in that particular context (eg. TLS 1.3 + * key schedule). For standard HKDF security guarantees use + * \c mbedtls_hkdf instead. + * * \param md A hash function; md.size denotes the length of the hash * function output in bytes. - * \param prk A pseudorandom key of at least md.size bytes. \p prk is usually, - * the output from the HKDF extract step. + * \param prk A pseudorandom key of at least md.size bytes. \p prk is + * usually the output from the HKDF extract step. * \param prk_len The length in bytes of \p prk. * \param info An optional context and application specific information * string. This can be a zero-length string. diff --git a/thirdparty/mbedtls/include/mbedtls/hmac_drbg.h b/thirdparty/mbedtls/include/mbedtls/hmac_drbg.h index 2608de8595..146367b9de 100644 --- a/thirdparty/mbedtls/include/mbedtls/hmac_drbg.h +++ b/thirdparty/mbedtls/include/mbedtls/hmac_drbg.h @@ -74,7 +74,7 @@ extern "C" { /** * HMAC_DRBG context. */ -typedef struct +typedef struct mbedtls_hmac_drbg_context { /* Working state: the key K is not stored explicitely, * but is implied by the HMAC context */ @@ -195,10 +195,13 @@ void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx, * \param additional Additional data to update state with, or NULL * \param add_len Length of additional data, or 0 * + * \return \c 0 on success, or an error from the underlying + * hash calculation. + * * \note Additional data is optional, pass NULL and 0 as second * third argument if no additional data is being used. */ -void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx, +int mbedtls_hmac_drbg_update_ret( mbedtls_hmac_drbg_context *ctx, const unsigned char *additional, size_t add_len ); /** @@ -257,6 +260,31 @@ int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len */ void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx ); +#if ! defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief HMAC_DRBG update state + * + * \deprecated Superseded by mbedtls_hmac_drbg_update_ret() + * in 2.16.0. + * + * \param ctx HMAC_DRBG context + * \param additional Additional data to update state with, or NULL + * \param add_len Length of additional data, or 0 + * + * \note Additional data is optional, pass NULL and 0 as second + * third argument if no additional data is being used. + */ +MBEDTLS_DEPRECATED void mbedtls_hmac_drbg_update( + mbedtls_hmac_drbg_context *ctx, + const unsigned char *additional, size_t add_len ); +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + #if defined(MBEDTLS_FS_IO) /** * \brief Write a seed file diff --git a/thirdparty/mbedtls/include/mbedtls/md.h b/thirdparty/mbedtls/include/mbedtls/md.h index 6b6f5c53dd..8bcf766a6c 100644 --- a/thirdparty/mbedtls/include/mbedtls/md.h +++ b/thirdparty/mbedtls/include/mbedtls/md.h @@ -39,6 +39,8 @@ #define MBEDTLS_ERR_MD_BAD_INPUT_DATA -0x5100 /**< Bad input parameters to function. */ #define MBEDTLS_ERR_MD_ALLOC_FAILED -0x5180 /**< Failed to allocate memory. */ #define MBEDTLS_ERR_MD_FILE_IO_ERROR -0x5200 /**< Opening or reading of file failed. */ + +/* MBEDTLS_ERR_MD_HW_ACCEL_FAILED is deprecated and should not be used. */ #define MBEDTLS_ERR_MD_HW_ACCEL_FAILED -0x5280 /**< MD hardware accelerator failed. */ #ifdef __cplusplus @@ -80,7 +82,8 @@ typedef struct mbedtls_md_info_t mbedtls_md_info_t; /** * The generic message-digest context. */ -typedef struct { +typedef struct mbedtls_md_context_t +{ /** Information about the associated message digest. */ const mbedtls_md_info_t *md_info; diff --git a/thirdparty/mbedtls/include/mbedtls/md2.h b/thirdparty/mbedtls/include/mbedtls/md2.h index 08e75b247b..f9bd98f804 100644 --- a/thirdparty/mbedtls/include/mbedtls/md2.h +++ b/thirdparty/mbedtls/include/mbedtls/md2.h @@ -37,6 +37,7 @@ #include <stddef.h> +/* MBEDTLS_ERR_MD2_HW_ACCEL_FAILED is deprecated and should not be used. */ #define MBEDTLS_ERR_MD2_HW_ACCEL_FAILED -0x002B /**< MD2 hardware accelerator failed */ #ifdef __cplusplus @@ -55,7 +56,7 @@ extern "C" { * stronger message digests instead. * */ -typedef struct +typedef struct mbedtls_md2_context { unsigned char cksum[16]; /*!< checksum of the data block */ unsigned char state[48]; /*!< intermediate digest state */ diff --git a/thirdparty/mbedtls/include/mbedtls/md4.h b/thirdparty/mbedtls/include/mbedtls/md4.h index 8ee4e5cabf..dc3c048949 100644 --- a/thirdparty/mbedtls/include/mbedtls/md4.h +++ b/thirdparty/mbedtls/include/mbedtls/md4.h @@ -38,6 +38,7 @@ #include <stddef.h> #include <stdint.h> +/* MBEDTLS_ERR_MD4_HW_ACCEL_FAILED is deprecated and should not be used. */ #define MBEDTLS_ERR_MD4_HW_ACCEL_FAILED -0x002D /**< MD4 hardware accelerator failed */ #ifdef __cplusplus @@ -56,7 +57,7 @@ extern "C" { * stronger message digests instead. * */ -typedef struct +typedef struct mbedtls_md4_context { uint32_t total[2]; /*!< number of bytes processed */ uint32_t state[4]; /*!< intermediate digest state */ diff --git a/thirdparty/mbedtls/include/mbedtls/md5.h b/thirdparty/mbedtls/include/mbedtls/md5.h index 43ead4b747..6c3354fd30 100644 --- a/thirdparty/mbedtls/include/mbedtls/md5.h +++ b/thirdparty/mbedtls/include/mbedtls/md5.h @@ -37,6 +37,7 @@ #include <stddef.h> #include <stdint.h> +/* MBEDTLS_ERR_MD5_HW_ACCEL_FAILED is deprecated and should not be used. */ #define MBEDTLS_ERR_MD5_HW_ACCEL_FAILED -0x002F /**< MD5 hardware accelerator failed */ #ifdef __cplusplus @@ -55,7 +56,7 @@ extern "C" { * stronger message digests instead. * */ -typedef struct +typedef struct mbedtls_md5_context { uint32_t total[2]; /*!< number of bytes processed */ uint32_t state[4]; /*!< intermediate digest state */ diff --git a/thirdparty/mbedtls/include/mbedtls/net_sockets.h b/thirdparty/mbedtls/include/mbedtls/net_sockets.h index 9f07eeb4d3..4c7ef00fe6 100644 --- a/thirdparty/mbedtls/include/mbedtls/net_sockets.h +++ b/thirdparty/mbedtls/include/mbedtls/net_sockets.h @@ -84,7 +84,7 @@ extern "C" { * (eg two file descriptors for combined IPv4 + IPv6 support, or additional * structures for hand-made UDP demultiplexing). */ -typedef struct +typedef struct mbedtls_net_context { int fd; /**< The underlying file descriptor */ } diff --git a/thirdparty/mbedtls/include/mbedtls/oid.h b/thirdparty/mbedtls/include/mbedtls/oid.h index f82554844c..6fbd018aaa 100644 --- a/thirdparty/mbedtls/include/mbedtls/oid.h +++ b/thirdparty/mbedtls/include/mbedtls/oid.h @@ -403,7 +403,8 @@ extern "C" { /** * \brief Base OID descriptor structure */ -typedef struct { +typedef struct mbedtls_oid_descriptor_t +{ const char *asn1; /*!< OID ASN.1 representation */ size_t asn1_len; /*!< length of asn1 */ const char *name; /*!< official name (e.g. from RFC) */ diff --git a/thirdparty/mbedtls/include/mbedtls/padlock.h b/thirdparty/mbedtls/include/mbedtls/padlock.h index 677936ebf8..7a5d083a95 100644 --- a/thirdparty/mbedtls/include/mbedtls/padlock.h +++ b/thirdparty/mbedtls/include/mbedtls/padlock.h @@ -3,6 +3,9 @@ * * \brief VIA PadLock ACE for HW encryption/decryption supported by some * processors + * + * \warning These functions are only for internal use by other library + * functions; you must not call them directly. */ /* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved @@ -57,7 +60,10 @@ extern "C" { #endif /** - * \brief PadLock detection routine + * \brief Internal PadLock detection routine + * + * \note This function is only for internal use by other library + * functions; you must not call it directly. * * \param feature The feature to detect * @@ -66,7 +72,10 @@ extern "C" { int mbedtls_padlock_has_support( int feature ); /** - * \brief PadLock AES-ECB block en(de)cryption + * \brief Internal PadLock AES-ECB block en(de)cryption + * + * \note This function is only for internal use by other library + * functions; you must not call it directly. * * \param ctx AES context * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT @@ -76,12 +85,15 @@ int mbedtls_padlock_has_support( int feature ); * \return 0 if success, 1 if operation failed */ int mbedtls_padlock_xcryptecb( mbedtls_aes_context *ctx, - int mode, - const unsigned char input[16], - unsigned char output[16] ); + int mode, + const unsigned char input[16], + unsigned char output[16] ); /** - * \brief PadLock AES-CBC buffer en(de)cryption + * \brief Internal PadLock AES-CBC buffer en(de)cryption + * + * \note This function is only for internal use by other library + * functions; you must not call it directly. * * \param ctx AES context * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT @@ -93,11 +105,11 @@ int mbedtls_padlock_xcryptecb( mbedtls_aes_context *ctx, * \return 0 if success, 1 if operation failed */ int mbedtls_padlock_xcryptcbc( mbedtls_aes_context *ctx, - int mode, - size_t length, - unsigned char iv[16], - const unsigned char *input, - unsigned char *output ); + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); #ifdef __cplusplus } diff --git a/thirdparty/mbedtls/include/mbedtls/pem.h b/thirdparty/mbedtls/include/mbedtls/pem.h index 2cf4c0a709..fa82f7bdbd 100644 --- a/thirdparty/mbedtls/include/mbedtls/pem.h +++ b/thirdparty/mbedtls/include/mbedtls/pem.h @@ -51,7 +51,7 @@ extern "C" { /** * \brief PEM context structure */ -typedef struct +typedef struct mbedtls_pem_context { unsigned char *buf; /*!< buffer for decoded data */ size_t buflen; /*!< length of the buffer */ diff --git a/thirdparty/mbedtls/include/mbedtls/pk.h b/thirdparty/mbedtls/include/mbedtls/pk.h index ee06b2fd20..91950f9407 100644 --- a/thirdparty/mbedtls/include/mbedtls/pk.h +++ b/thirdparty/mbedtls/include/mbedtls/pk.h @@ -64,6 +64,8 @@ #define MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE -0x3A00 /**< Elliptic curve is unsupported (only NIST curves are supported). */ #define MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE -0x3980 /**< Unavailable feature, e.g. RSA disabled for RSA key. */ #define MBEDTLS_ERR_PK_SIG_LEN_MISMATCH -0x3900 /**< The buffer contains a valid signature followed by more data. */ + +/* MBEDTLS_ERR_PK_HW_ACCEL_FAILED is deprecated and should not be used. */ #define MBEDTLS_ERR_PK_HW_ACCEL_FAILED -0x3880 /**< PK hardware accelerator failed. */ #ifdef __cplusplus @@ -87,7 +89,7 @@ typedef enum { * \brief Options for RSASSA-PSS signature verification. * See \c mbedtls_rsa_rsassa_pss_verify_ext() */ -typedef struct +typedef struct mbedtls_pk_rsassa_pss_options { mbedtls_md_type_t mgf1_hash_id; int expected_salt_len; @@ -107,7 +109,7 @@ typedef enum /** * \brief Item to send to the debug module */ -typedef struct +typedef struct mbedtls_pk_debug_item { mbedtls_pk_debug_type type; const char *name; @@ -125,12 +127,26 @@ typedef struct mbedtls_pk_info_t mbedtls_pk_info_t; /** * \brief Public key container */ -typedef struct +typedef struct mbedtls_pk_context { - const mbedtls_pk_info_t * pk_info; /**< Public key informations */ + const mbedtls_pk_info_t * pk_info; /**< Public key information */ void * pk_ctx; /**< Underlying public key context */ } mbedtls_pk_context; +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +/** + * \brief Context for resuming operations + */ +typedef struct +{ + const mbedtls_pk_info_t * pk_info; /**< Public key information */ + void * rs_ctx; /**< Underlying restart context */ +} mbedtls_pk_restart_ctx; +#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ +/* Now we can declare functions that take a pointer to that */ +typedef void mbedtls_pk_restart_ctx; +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + #if defined(MBEDTLS_RSA_C) /** * Quick access to an RSA context inside a PK context. @@ -181,20 +197,45 @@ typedef size_t (*mbedtls_pk_rsa_alt_key_len_func)( void *ctx ); const mbedtls_pk_info_t *mbedtls_pk_info_from_type( mbedtls_pk_type_t pk_type ); /** - * \brief Initialize a mbedtls_pk_context (as NONE) + * \brief Initialize a #mbedtls_pk_context (as NONE). + * + * \param ctx The context to initialize. + * This must not be \c NULL. */ void mbedtls_pk_init( mbedtls_pk_context *ctx ); /** - * \brief Free a mbedtls_pk_context + * \brief Free the components of a #mbedtls_pk_context. + * + * \param ctx The context to clear. It must have been initialized. + * If this is \c NULL, this function does nothing. */ void mbedtls_pk_free( mbedtls_pk_context *ctx ); +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +/** + * \brief Initialize a restart context + * + * \param ctx The context to initialize. + * This must not be \c NULL. + */ +void mbedtls_pk_restart_init( mbedtls_pk_restart_ctx *ctx ); + +/** + * \brief Free the components of a restart context + * + * \param ctx The context to clear. It must have been initialized. + * If this is \c NULL, this function does nothing. + */ +void mbedtls_pk_restart_free( mbedtls_pk_restart_ctx *ctx ); +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + /** * \brief Initialize a PK context with the information given * and allocates the type-specific PK subcontext. * - * \param ctx Context to initialize. Must be empty (type NONE). + * \param ctx Context to initialize. It must not have been set + * up yet (type #MBEDTLS_PK_NONE). * \param info Information to use * * \return 0 on success, @@ -210,7 +251,8 @@ int mbedtls_pk_setup( mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info ); /** * \brief Initialize an RSA-alt context * - * \param ctx Context to initialize. Must be empty (type NONE). + * \param ctx Context to initialize. It must not have been set + * up yet (type #MBEDTLS_PK_NONE). * \param key RSA key pointer * \param decrypt_func Decryption function * \param sign_func Signing function @@ -230,7 +272,7 @@ int mbedtls_pk_setup_rsa_alt( mbedtls_pk_context *ctx, void * key, /** * \brief Get the size in bits of the underlying key * - * \param ctx Context to use + * \param ctx The context to query. It must have been initialized. * * \return Key size in bits, or 0 on error */ @@ -238,7 +280,8 @@ size_t mbedtls_pk_get_bitlen( const mbedtls_pk_context *ctx ); /** * \brief Get the length in bytes of the underlying key - * \param ctx Context to use + * + * \param ctx The context to query. It must have been initialized. * * \return Key length in bytes, or 0 on error */ @@ -250,18 +293,21 @@ static inline size_t mbedtls_pk_get_len( const mbedtls_pk_context *ctx ) /** * \brief Tell if a context can do the operation given by type * - * \param ctx Context to test - * \param type Target type + * \param ctx The context to query. It must have been initialized. + * \param type The desired type. * - * \return 0 if context can't do the operations, - * 1 otherwise. + * \return 1 if the context can do operations on the given type. + * \return 0 if the context cannot do the operations on the given + * type. This is always the case for a context that has + * been initialized but not set up, or that has been + * cleared with mbedtls_pk_free(). */ int mbedtls_pk_can_do( const mbedtls_pk_context *ctx, mbedtls_pk_type_t type ); /** * \brief Verify signature (including padding if relevant). * - * \param ctx PK context to use + * \param ctx The PK context to use. It must have been set up. * \param md_alg Hash algorithm used (see notes) * \param hash Hash of the message to sign * \param hash_len Hash length or 0 (see notes) @@ -287,12 +333,38 @@ int mbedtls_pk_verify( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, const unsigned char *sig, size_t sig_len ); /** + * \brief Restartable version of \c mbedtls_pk_verify() + * + * \note Performs the same job as \c mbedtls_pk_verify(), but can + * return early and restart according to the limit set with + * \c mbedtls_ecp_set_max_ops() to reduce blocking for ECC + * operations. For RSA, same as \c mbedtls_pk_verify(). + * + * \param ctx The PK context to use. It must have been set up. + * \param md_alg Hash algorithm used (see notes) + * \param hash Hash of the message to sign + * \param hash_len Hash length or 0 (see notes) + * \param sig Signature to verify + * \param sig_len Signature length + * \param rs_ctx Restart context (NULL to disable restart) + * + * \return See \c mbedtls_pk_verify(), or + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + */ +int mbedtls_pk_verify_restartable( mbedtls_pk_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len, + mbedtls_pk_restart_ctx *rs_ctx ); + +/** * \brief Verify signature, with options. * (Includes verification of the padding depending on type.) * * \param type Signature type (inc. possible padding type) to verify * \param options Pointer to type-specific options, or NULL - * \param ctx PK context to use + * \param ctx The PK context to use. It must have been set up. * \param md_alg Hash algorithm used (see notes) * \param hash Hash of the message to sign * \param hash_len Hash length or 0 (see notes) @@ -323,7 +395,8 @@ int mbedtls_pk_verify_ext( mbedtls_pk_type_t type, const void *options, /** * \brief Make signature, including padding if relevant. * - * \param ctx PK context to use - must hold a private key + * \param ctx The PK context to use. It must have been set up + * with a private key. * \param md_alg Hash algorithm used (see notes) * \param hash Hash of the message to sign * \param hash_len Hash length or 0 (see notes) @@ -350,9 +423,40 @@ int mbedtls_pk_sign( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); /** + * \brief Restartable version of \c mbedtls_pk_sign() + * + * \note Performs the same job as \c mbedtls_pk_sign(), but can + * return early and restart according to the limit set with + * \c mbedtls_ecp_set_max_ops() to reduce blocking for ECC + * operations. For RSA, same as \c mbedtls_pk_sign(). + * + * \param ctx The PK context to use. It must have been set up + * with a private key. + * \param md_alg Hash algorithm used (see notes) + * \param hash Hash of the message to sign + * \param hash_len Hash length or 0 (see notes) + * \param sig Place to write the signature + * \param sig_len Number of bytes written + * \param f_rng RNG function + * \param p_rng RNG parameter + * \param rs_ctx Restart context (NULL to disable restart) + * + * \return See \c mbedtls_pk_sign(), or + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + */ +int mbedtls_pk_sign_restartable( mbedtls_pk_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + mbedtls_pk_restart_ctx *rs_ctx ); + +/** * \brief Decrypt message (including padding if relevant). * - * \param ctx PK context to use - must hold a private key + * \param ctx The PK context to use. It must have been set up + * with a private key. * \param input Input to decrypt * \param ilen Input size * \param output Decrypted output @@ -373,7 +477,7 @@ int mbedtls_pk_decrypt( mbedtls_pk_context *ctx, /** * \brief Encrypt message (including padding if relevant). * - * \param ctx PK context to use + * \param ctx The PK context to use. It must have been set up. * \param input Message to encrypt * \param ilen Message size * \param output Encrypted output @@ -404,7 +508,7 @@ int mbedtls_pk_check_pair( const mbedtls_pk_context *pub, const mbedtls_pk_conte /** * \brief Export debug information * - * \param ctx Context to use + * \param ctx The PK context to use. It must have been initialized. * \param items Place to write debug items * * \return 0 on success or MBEDTLS_ERR_PK_BAD_INPUT_DATA @@ -414,7 +518,7 @@ int mbedtls_pk_debug( const mbedtls_pk_context *ctx, mbedtls_pk_debug_item *item /** * \brief Access the type name * - * \param ctx Context to use + * \param ctx The PK context to use. It must have been initialized. * * \return Type name on success, or "invalid PK" */ @@ -423,9 +527,10 @@ const char * mbedtls_pk_get_name( const mbedtls_pk_context *ctx ); /** * \brief Get the key type * - * \param ctx Context to use + * \param ctx The PK context to use. It must have been initialized. * - * \return Type on success, or MBEDTLS_PK_NONE + * \return Type on success. + * \return #MBEDTLS_PK_NONE for a context that has not been set up. */ mbedtls_pk_type_t mbedtls_pk_get_type( const mbedtls_pk_context *ctx ); @@ -434,12 +539,22 @@ mbedtls_pk_type_t mbedtls_pk_get_type( const mbedtls_pk_context *ctx ); /** * \brief Parse a private key in PEM or DER format * - * \param ctx key to be initialized - * \param key input buffer - * \param keylen size of the buffer - * (including the terminating null byte for PEM data) - * \param pwd password for decryption (optional) - * \param pwdlen size of the password + * \param ctx The PK context to fill. It must have been initialized + * but not set up. + * \param key Input buffer to parse. + * The buffer must contain the input exactly, with no + * extra trailing material. For PEM, the buffer must + * contain a null-terminated string. + * \param keylen Size of \b key in bytes. + * For PEM data, this includes the terminating null byte, + * so \p keylen must be equal to `strlen(key) + 1`. + * \param pwd Optional password for decryption. + * Pass \c NULL if expecting a non-encrypted key. + * Pass a string of \p pwdlen bytes if expecting an encrypted + * key; a non-encrypted key will also be accepted. + * The empty password is not supported. + * \param pwdlen Size of the password in bytes. + * Ignored if \p pwd is \c NULL. * * \note On entry, ctx must be empty, either freshly initialised * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a @@ -457,10 +572,15 @@ int mbedtls_pk_parse_key( mbedtls_pk_context *ctx, /** * \brief Parse a public key in PEM or DER format * - * \param ctx key to be initialized - * \param key input buffer - * \param keylen size of the buffer - * (including the terminating null byte for PEM data) + * \param ctx The PK context to fill. It must have been initialized + * but not set up. + * \param key Input buffer to parse. + * The buffer must contain the input exactly, with no + * extra trailing material. For PEM, the buffer must + * contain a null-terminated string. + * \param keylen Size of \b key in bytes. + * For PEM data, this includes the terminating null byte, + * so \p keylen must be equal to `strlen(key) + 1`. * * \note On entry, ctx must be empty, either freshly initialised * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a @@ -478,9 +598,14 @@ int mbedtls_pk_parse_public_key( mbedtls_pk_context *ctx, /** * \brief Load and parse a private key * - * \param ctx key to be initialized + * \param ctx The PK context to fill. It must have been initialized + * but not set up. * \param path filename to read the private key from - * \param password password to decrypt the file (can be NULL) + * \param password Optional password to decrypt the file. + * Pass \c NULL if expecting a non-encrypted key. + * Pass a null-terminated string if expecting an encrypted + * key; a non-encrypted key will also be accepted. + * The empty password is not supported. * * \note On entry, ctx must be empty, either freshly initialised * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a @@ -497,7 +622,8 @@ int mbedtls_pk_parse_keyfile( mbedtls_pk_context *ctx, /** * \brief Load and parse a public key * - * \param ctx key to be initialized + * \param ctx The PK context to fill. It must have been initialized + * but not set up. * \param path filename to read the public key from * * \note On entry, ctx must be empty, either freshly initialised @@ -520,7 +646,7 @@ int mbedtls_pk_parse_public_keyfile( mbedtls_pk_context *ctx, const char *path ) * return value to determine where you should start * using the buffer * - * \param ctx private to write away + * \param ctx PK context which must contain a valid private key. * \param buf buffer to write to * \param size size of the buffer * @@ -535,7 +661,7 @@ int mbedtls_pk_write_key_der( mbedtls_pk_context *ctx, unsigned char *buf, size_ * return value to determine where you should start * using the buffer * - * \param ctx public key to write away + * \param ctx PK context which must contain a valid public or private key. * \param buf buffer to write to * \param size size of the buffer * @@ -548,9 +674,10 @@ int mbedtls_pk_write_pubkey_der( mbedtls_pk_context *ctx, unsigned char *buf, si /** * \brief Write a public key to a PEM string * - * \param ctx public key to write away - * \param buf buffer to write to - * \param size size of the buffer + * \param ctx PK context which must contain a valid public or private key. + * \param buf Buffer to write to. The output includes a + * terminating null byte. + * \param size Size of the buffer in bytes. * * \return 0 if successful, or a specific error code */ @@ -559,9 +686,10 @@ int mbedtls_pk_write_pubkey_pem( mbedtls_pk_context *ctx, unsigned char *buf, si /** * \brief Write a private key to a PKCS#1 or SEC1 PEM string * - * \param ctx private to write away - * \param buf buffer to write to - * \param size size of the buffer + * \param ctx PK context which must contain a valid private key. + * \param buf Buffer to write to. The output includes a + * terminating null byte. + * \param size Size of the buffer in bytes. * * \return 0 if successful, or a specific error code */ @@ -580,7 +708,8 @@ int mbedtls_pk_write_key_pem( mbedtls_pk_context *ctx, unsigned char *buf, size_ * * \param p the position in the ASN.1 data * \param end end of the buffer - * \param pk the key to fill + * \param pk The PK context to fill. It must have been initialized + * but not set up. * * \return 0 if successful, or a specific PK error code */ @@ -595,7 +724,7 @@ int mbedtls_pk_parse_subpubkey( unsigned char **p, const unsigned char *end, * * \param p reference to current position pointer * \param start start of the buffer (for bounds-checking) - * \param key public key to write away + * \param key PK context which must contain a valid public or private key. * * \return the length written or a negative error code */ diff --git a/thirdparty/mbedtls/include/mbedtls/pk_internal.h b/thirdparty/mbedtls/include/mbedtls/pk_internal.h index 3dae0fc5b2..48b7a5f7bf 100644 --- a/thirdparty/mbedtls/include/mbedtls/pk_internal.h +++ b/thirdparty/mbedtls/include/mbedtls/pk_internal.h @@ -59,6 +59,21 @@ struct mbedtls_pk_info_t int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + /** Verify signature (restartable) */ + int (*verify_rs_func)( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len, + void *rs_ctx ); + + /** Make signature (restartable) */ + int (*sign_rs_func)( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, void *rs_ctx ); +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + /** Decrypt message */ int (*decrypt_func)( void *ctx, const unsigned char *input, size_t ilen, unsigned char *output, size_t *olen, size_t osize, @@ -80,6 +95,14 @@ struct mbedtls_pk_info_t /** Free the given context */ void (*ctx_free_func)( void *ctx ); +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + /** Allocate the restart context */ + void * (*rs_alloc_func)( void ); + + /** Free the restart context */ + void (*rs_free_func)( void *rs_ctx ); +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + /** Interface with the debug module */ void (*debug_func)( const void *ctx, mbedtls_pk_debug_item *items ); diff --git a/thirdparty/mbedtls/include/mbedtls/pkcs11.h b/thirdparty/mbedtls/include/mbedtls/pkcs11.h index bf65c55a79..02427ddc1e 100644 --- a/thirdparty/mbedtls/include/mbedtls/pkcs11.h +++ b/thirdparty/mbedtls/include/mbedtls/pkcs11.h @@ -50,7 +50,8 @@ extern "C" { /** * Context for PKCS #11 private keys. */ -typedef struct { +typedef struct mbedtls_pkcs11_context +{ pkcs11h_certificate_t pkcs11h_cert; int len; } mbedtls_pkcs11_context; diff --git a/thirdparty/mbedtls/include/mbedtls/pkcs12.h b/thirdparty/mbedtls/include/mbedtls/pkcs12.h index a621ef5b15..69f04177c8 100644 --- a/thirdparty/mbedtls/include/mbedtls/pkcs12.h +++ b/thirdparty/mbedtls/include/mbedtls/pkcs12.h @@ -46,6 +46,8 @@ extern "C" { #endif +#if defined(MBEDTLS_ASN1_PARSE_C) + /** * \brief PKCS12 Password Based function (encryption / decryption) * for pbeWithSHAAnd128BitRC4 @@ -87,6 +89,8 @@ int mbedtls_pkcs12_pbe( mbedtls_asn1_buf *pbe_params, int mode, const unsigned char *input, size_t len, unsigned char *output ); +#endif /* MBEDTLS_ASN1_PARSE_C */ + /** * \brief The PKCS#12 derivation function uses a password and a salt * to produce pseudo-random bits for a particular "purpose". diff --git a/thirdparty/mbedtls/include/mbedtls/pkcs5.h b/thirdparty/mbedtls/include/mbedtls/pkcs5.h index 9a3c9fddcc..d4bb36dfae 100644 --- a/thirdparty/mbedtls/include/mbedtls/pkcs5.h +++ b/thirdparty/mbedtls/include/mbedtls/pkcs5.h @@ -44,6 +44,8 @@ extern "C" { #endif +#if defined(MBEDTLS_ASN1_PARSE_C) + /** * \brief PKCS#5 PBES2 function * @@ -62,6 +64,8 @@ int mbedtls_pkcs5_pbes2( const mbedtls_asn1_buf *pbe_params, int mode, const unsigned char *data, size_t datalen, unsigned char *output ); +#endif /* MBEDTLS_ASN1_PARSE_C */ + /** * \brief PKCS#5 PBKDF2 using HMAC * diff --git a/thirdparty/mbedtls/include/mbedtls/platform.h b/thirdparty/mbedtls/include/mbedtls/platform.h index 624cc642ac..89fe8a7b19 100644 --- a/thirdparty/mbedtls/include/mbedtls/platform.h +++ b/thirdparty/mbedtls/include/mbedtls/platform.h @@ -43,6 +43,9 @@ #include "platform_time.h" #endif +#define MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED -0x0070 /**< Hardware accelerator failed */ +#define MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED -0x0072 /**< The requested feature is not supported by the platform */ + #ifdef __cplusplus extern "C" { #endif @@ -315,7 +318,8 @@ int mbedtls_platform_set_nv_seed( * \note This structure may be used to assist platform-specific * setup or teardown operations. */ -typedef struct { +typedef struct mbedtls_platform_context +{ char dummy; /**< A placeholder member, as empty structs are not portable. */ } mbedtls_platform_context; diff --git a/thirdparty/mbedtls/include/mbedtls/platform_util.h b/thirdparty/mbedtls/include/mbedtls/platform_util.h index 84f0732eeb..b0e72ad149 100644 --- a/thirdparty/mbedtls/include/mbedtls/platform_util.h +++ b/thirdparty/mbedtls/include/mbedtls/platform_util.h @@ -25,12 +25,104 @@ #ifndef MBEDTLS_PLATFORM_UTIL_H #define MBEDTLS_PLATFORM_UTIL_H +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + #include <stddef.h> +#if defined(MBEDTLS_HAVE_TIME_DATE) +#include "mbedtls/platform_time.h" +#include <time.h> +#endif /* MBEDTLS_HAVE_TIME_DATE */ #ifdef __cplusplus extern "C" { #endif +#if defined(MBEDTLS_CHECK_PARAMS) + +#if defined(MBEDTLS_PARAM_FAILED) +/** An alternative definition of MBEDTLS_PARAM_FAILED has been set in config.h. + * + * This flag can be used to check whether it is safe to assume that + * MBEDTLS_PARAM_FAILED() will expand to a call to mbedtls_param_failed(). + */ +#define MBEDTLS_PARAM_FAILED_ALT +#else /* MBEDTLS_PARAM_FAILED */ +#define MBEDTLS_PARAM_FAILED( cond ) \ + mbedtls_param_failed( #cond, __FILE__, __LINE__ ) + +/** + * \brief User supplied callback function for parameter validation failure. + * See #MBEDTLS_CHECK_PARAMS for context. + * + * This function will be called unless an alternative treatement + * is defined through the #MBEDTLS_PARAM_FAILED macro. + * + * This function can return, and the operation will be aborted, or + * alternatively, through use of setjmp()/longjmp() can resume + * execution in the application code. + * + * \param failure_condition The assertion that didn't hold. + * \param file The file where the assertion failed. + * \param line The line in the file where the assertion failed. + */ +void mbedtls_param_failed( const char *failure_condition, + const char *file, + int line ); +#endif /* MBEDTLS_PARAM_FAILED */ + +/* Internal macro meant to be called only from within the library. */ +#define MBEDTLS_INTERNAL_VALIDATE_RET( cond, ret ) \ + do { \ + if( !(cond) ) \ + { \ + MBEDTLS_PARAM_FAILED( cond ); \ + return( ret ); \ + } \ + } while( 0 ) + +/* Internal macro meant to be called only from within the library. */ +#define MBEDTLS_INTERNAL_VALIDATE( cond ) \ + do { \ + if( !(cond) ) \ + { \ + MBEDTLS_PARAM_FAILED( cond ); \ + return; \ + } \ + } while( 0 ) + +#else /* MBEDTLS_CHECK_PARAMS */ + +/* Internal macros meant to be called only from within the library. */ +#define MBEDTLS_INTERNAL_VALIDATE_RET( cond, ret ) do { } while( 0 ) +#define MBEDTLS_INTERNAL_VALIDATE( cond ) do { } while( 0 ) + +#endif /* MBEDTLS_CHECK_PARAMS */ + +/* Internal helper macros for deprecating API constants. */ +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +/* Deliberately don't (yet) export MBEDTLS_DEPRECATED here + * to avoid conflict with other headers which define and use + * it, too. We might want to move all these definitions here at + * some point for uniformity. */ +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +MBEDTLS_DEPRECATED typedef char const * mbedtls_deprecated_string_constant_t; +#define MBEDTLS_DEPRECATED_STRING_CONSTANT( VAL ) \ + ( (mbedtls_deprecated_string_constant_t) ( VAL ) ) +MBEDTLS_DEPRECATED typedef int mbedtls_deprecated_numeric_constant_t; +#define MBEDTLS_DEPRECATED_NUMERIC_CONSTANT( VAL ) \ + ( (mbedtls_deprecated_numeric_constant_t) ( VAL ) ) +#undef MBEDTLS_DEPRECATED +#else /* MBEDTLS_DEPRECATED_WARNING */ +#define MBEDTLS_DEPRECATED_STRING_CONSTANT( VAL ) VAL +#define MBEDTLS_DEPRECATED_NUMERIC_CONSTANT( VAL ) VAL +#endif /* MBEDTLS_DEPRECATED_WARNING */ +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + /** * \brief Securely zeroize a buffer * @@ -55,6 +147,37 @@ extern "C" { */ void mbedtls_platform_zeroize( void *buf, size_t len ); +#if defined(MBEDTLS_HAVE_TIME_DATE) +/** + * \brief Platform-specific implementation of gmtime_r() + * + * The function is a thread-safe abstraction that behaves + * similarly to the gmtime_r() function from Unix/POSIX. + * + * Mbed TLS will try to identify the underlying platform and + * make use of an appropriate underlying implementation (e.g. + * gmtime_r() for POSIX and gmtime_s() for Windows). If this is + * not possible, then gmtime() will be used. In this case, calls + * from the library to gmtime() will be guarded by the mutex + * mbedtls_threading_gmtime_mutex if MBEDTLS_THREADING_C is + * enabled. It is recommended that calls from outside the library + * are also guarded by this mutex. + * + * If MBEDTLS_PLATFORM_GMTIME_R_ALT is defined, then Mbed TLS will + * unconditionally use the alternative implementation for + * mbedtls_platform_gmtime_r() supplied by the user at compile time. + * + * \param tt Pointer to an object containing time (in seconds) since the + * epoch to be converted + * \param tm_buf Pointer to an object where the results will be stored + * + * \return Pointer to an object of type struct tm on success, otherwise + * NULL + */ +struct tm *mbedtls_platform_gmtime_r( const mbedtls_time_t *tt, + struct tm *tm_buf ); +#endif /* MBEDTLS_HAVE_TIME_DATE */ + #ifdef __cplusplus } #endif diff --git a/thirdparty/mbedtls/include/mbedtls/poly1305.h b/thirdparty/mbedtls/include/mbedtls/poly1305.h index 54b50abc25..05866a2da6 100644 --- a/thirdparty/mbedtls/include/mbedtls/poly1305.h +++ b/thirdparty/mbedtls/include/mbedtls/poly1305.h @@ -43,7 +43,13 @@ #include <stddef.h> #define MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA -0x0057 /**< Invalid input parameter(s). */ + +/* MBEDTLS_ERR_POLY1305_FEATURE_UNAVAILABLE is deprecated and should not be + * used. */ #define MBEDTLS_ERR_POLY1305_FEATURE_UNAVAILABLE -0x0059 /**< Feature not available. For example, s part of the API is not implemented. */ + +/* MBEDTLS_ERR_POLY1305_HW_ACCEL_FAILED is deprecated and should not be used. + */ #define MBEDTLS_ERR_POLY1305_HW_ACCEL_FAILED -0x005B /**< Poly1305 hardware accelerator failed. */ #ifdef __cplusplus @@ -52,7 +58,7 @@ extern "C" { #if !defined(MBEDTLS_POLY1305_ALT) -typedef struct +typedef struct mbedtls_poly1305_context { uint32_t r[4]; /** The value for 'r' (low 128 bits of the key). */ uint32_t s[4]; /** The value for 's' (high 128 bits of the key). */ @@ -78,14 +84,18 @@ mbedtls_poly1305_context; * \c mbedtls_poly1305_finish(), then finally * \c mbedtls_poly1305_free(). * - * \param ctx The Poly1305 context to initialize. + * \param ctx The Poly1305 context to initialize. This must + * not be \c NULL. */ void mbedtls_poly1305_init( mbedtls_poly1305_context *ctx ); /** - * \brief This function releases and clears the specified Poly1305 context. + * \brief This function releases and clears the specified + * Poly1305 context. * - * \param ctx The Poly1305 context to clear. + * \param ctx The Poly1305 context to clear. This may be \c NULL, in which + * case this function is a no-op. If it is not \c NULL, it must + * point to an initialized Poly1305 context. */ void mbedtls_poly1305_free( mbedtls_poly1305_context *ctx ); @@ -96,11 +106,11 @@ void mbedtls_poly1305_free( mbedtls_poly1305_context *ctx ); * invocation of Poly1305. * * \param ctx The Poly1305 context to which the key should be bound. - * \param key The buffer containing the 256-bit key. + * This must be initialized. + * \param key The buffer containing the \c 32 Byte (\c 256 Bit) key. * * \return \c 0 on success. - * \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA - * if ctx or key are NULL. + * \return A negative error code on failure. */ int mbedtls_poly1305_starts( mbedtls_poly1305_context *ctx, const unsigned char key[32] ); @@ -114,13 +124,14 @@ int mbedtls_poly1305_starts( mbedtls_poly1305_context *ctx, * It can be called repeatedly to process a stream of data. * * \param ctx The Poly1305 context to use for the Poly1305 operation. - * \param ilen The length of the input data (in bytes). Any value is accepted. + * This must be initialized and bound to a key. + * \param ilen The length of the input data in Bytes. + * Any value is accepted. * \param input The buffer holding the input data. - * This pointer can be NULL if ilen == 0. + * This pointer can be \c NULL if `ilen == 0`. * * \return \c 0 on success. - * \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA - * if ctx or input are NULL. + * \return A negative error code on failure. */ int mbedtls_poly1305_update( mbedtls_poly1305_context *ctx, const unsigned char *input, @@ -131,12 +142,12 @@ int mbedtls_poly1305_update( mbedtls_poly1305_context *ctx, * Authentication Code (MAC). * * \param ctx The Poly1305 context to use for the Poly1305 operation. - * \param mac The buffer to where the MAC is written. Must be big enough - * to hold the 16-byte MAC. + * This must be initialized and bound to a key. + * \param mac The buffer to where the MAC is written. This must + * be a writable buffer of length \c 16 Bytes. * * \return \c 0 on success. - * \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA - * if ctx or mac are NULL. + * \return A negative error code on failure. */ int mbedtls_poly1305_finish( mbedtls_poly1305_context *ctx, unsigned char mac[16] ); @@ -148,16 +159,16 @@ int mbedtls_poly1305_finish( mbedtls_poly1305_context *ctx, * \warning The key must be unique and unpredictable for each * invocation of Poly1305. * - * \param key The buffer containing the 256-bit key. - * \param ilen The length of the input data (in bytes). Any value is accepted. + * \param key The buffer containing the \c 32 Byte (\c 256 Bit) key. + * \param ilen The length of the input data in Bytes. + * Any value is accepted. * \param input The buffer holding the input data. - * This pointer can be NULL if ilen == 0. - * \param mac The buffer to where the MAC is written. Must be big enough - * to hold the 16-byte MAC. + * This pointer can be \c NULL if `ilen == 0`. + * \param mac The buffer to where the MAC is written. This must be + * a writable buffer of length \c 16 Bytes. * * \return \c 0 on success. - * \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA - * if key, input, or mac are NULL. + * \return A negative error code on failure. */ int mbedtls_poly1305_mac( const unsigned char key[32], const unsigned char *input, diff --git a/thirdparty/mbedtls/include/mbedtls/ripemd160.h b/thirdparty/mbedtls/include/mbedtls/ripemd160.h index a0dac0c360..c74b7d2c6c 100644 --- a/thirdparty/mbedtls/include/mbedtls/ripemd160.h +++ b/thirdparty/mbedtls/include/mbedtls/ripemd160.h @@ -33,6 +33,8 @@ #include <stddef.h> #include <stdint.h> +/* MBEDTLS_ERR_RIPEMD160_HW_ACCEL_FAILED is deprecated and should not be used. + */ #define MBEDTLS_ERR_RIPEMD160_HW_ACCEL_FAILED -0x0031 /**< RIPEMD160 hardware accelerator failed */ #ifdef __cplusplus @@ -46,7 +48,7 @@ extern "C" { /** * \brief RIPEMD-160 context structure */ -typedef struct +typedef struct mbedtls_ripemd160_context { uint32_t total[2]; /*!< number of bytes processed */ uint32_t state[5]; /*!< intermediate digest state */ diff --git a/thirdparty/mbedtls/include/mbedtls/rsa.h b/thirdparty/mbedtls/include/mbedtls/rsa.h index 19eb2ee74c..ed65a34452 100644 --- a/thirdparty/mbedtls/include/mbedtls/rsa.h +++ b/thirdparty/mbedtls/include/mbedtls/rsa.h @@ -55,7 +55,12 @@ #define MBEDTLS_ERR_RSA_VERIFY_FAILED -0x4380 /**< The PKCS#1 verification failed. */ #define MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE -0x4400 /**< The output buffer for decryption is not large enough. */ #define MBEDTLS_ERR_RSA_RNG_FAILED -0x4480 /**< The random generator failed to generate non-zeros. */ + +/* MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION is deprecated and should not be used. + */ #define MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION -0x4500 /**< The implementation does not offer the requested operation, for example, because of security violations or lack of functionality. */ + +/* MBEDTLS_ERR_RSA_HW_ACCEL_FAILED is deprecated and should not be used. */ #define MBEDTLS_ERR_RSA_HW_ACCEL_FAILED -0x4580 /**< RSA hardware accelerator failed. */ /* @@ -92,7 +97,7 @@ extern "C" { * is deprecated. All manipulation should instead be done through * the public interface functions. */ -typedef struct +typedef struct mbedtls_rsa_context { int ver; /*!< Always 0.*/ size_t len; /*!< The size of \p N in Bytes. */ @@ -153,15 +158,16 @@ mbedtls_rsa_context; * making signatures, but can be overriden for verifying them. * If set to #MBEDTLS_MD_NONE, it is always overriden. * - * \param ctx The RSA context to initialize. - * \param padding Selects padding mode: #MBEDTLS_RSA_PKCS_V15 or - * #MBEDTLS_RSA_PKCS_V21. - * \param hash_id The hash identifier of #mbedtls_md_type_t type, if - * \p padding is #MBEDTLS_RSA_PKCS_V21. + * \param ctx The RSA context to initialize. This must not be \c NULL. + * \param padding The padding mode to use. This must be either + * #MBEDTLS_RSA_PKCS_V15 or #MBEDTLS_RSA_PKCS_V21. + * \param hash_id The hash identifier of ::mbedtls_md_type_t type, if + * \p padding is #MBEDTLS_RSA_PKCS_V21. It is unused + * otherwise. */ void mbedtls_rsa_init( mbedtls_rsa_context *ctx, int padding, - int hash_id); + int hash_id ); /** * \brief This function imports a set of core parameters into an @@ -183,11 +189,11 @@ void mbedtls_rsa_init( mbedtls_rsa_context *ctx, * for the lifetime of the RSA context being set up. * * \param ctx The initialized RSA context to store the parameters in. - * \param N The RSA modulus, or NULL. - * \param P The first prime factor of \p N, or NULL. - * \param Q The second prime factor of \p N, or NULL. - * \param D The private exponent, or NULL. - * \param E The public exponent, or NULL. + * \param N The RSA modulus. This may be \c NULL. + * \param P The first prime factor of \p N. This may be \c NULL. + * \param Q The second prime factor of \p N. This may be \c NULL. + * \param D The private exponent. This may be \c NULL. + * \param E The public exponent. This may be \c NULL. * * \return \c 0 on success. * \return A non-zero error code on failure. @@ -217,16 +223,16 @@ int mbedtls_rsa_import( mbedtls_rsa_context *ctx, * for the lifetime of the RSA context being set up. * * \param ctx The initialized RSA context to store the parameters in. - * \param N The RSA modulus, or NULL. - * \param N_len The Byte length of \p N, ignored if \p N == NULL. - * \param P The first prime factor of \p N, or NULL. - * \param P_len The Byte length of \p P, ignored if \p P == NULL. - * \param Q The second prime factor of \p N, or NULL. - * \param Q_len The Byte length of \p Q, ignored if \p Q == NULL. - * \param D The private exponent, or NULL. - * \param D_len The Byte length of \p D, ignored if \p D == NULL. - * \param E The public exponent, or NULL. - * \param E_len The Byte length of \p E, ignored if \p E == NULL. + * \param N The RSA modulus. This may be \c NULL. + * \param N_len The Byte length of \p N; it is ignored if \p N == NULL. + * \param P The first prime factor of \p N. This may be \c NULL. + * \param P_len The Byte length of \p P; it ns ignored if \p P == NULL. + * \param Q The second prime factor of \p N. This may be \c NULL. + * \param Q_len The Byte length of \p Q; it is ignored if \p Q == NULL. + * \param D The private exponent. This may be \c NULL. + * \param D_len The Byte length of \p D; it is ignored if \p D == NULL. + * \param E The public exponent. This may be \c NULL. + * \param E_len The Byte length of \p E; it is ignored if \p E == NULL. * * \return \c 0 on success. * \return A non-zero error code on failure. @@ -281,7 +287,7 @@ int mbedtls_rsa_complete( mbedtls_rsa_context *ctx ); * zero Bytes. * * Possible reasons for returning - * #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION:<ul> + * #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED:<ul> * <li>An alternative RSA implementation is in use, which * stores the key externally, and either cannot or should * not export it into RAM.</li> @@ -294,14 +300,19 @@ int mbedtls_rsa_complete( mbedtls_rsa_context *ctx ); * the RSA context stays intact and remains usable. * * \param ctx The initialized RSA context. - * \param N The MPI to hold the RSA modulus, or NULL. - * \param P The MPI to hold the first prime factor of \p N, or NULL. - * \param Q The MPI to hold the second prime factor of \p N, or NULL. - * \param D The MPI to hold the private exponent, or NULL. - * \param E The MPI to hold the public exponent, or NULL. + * \param N The MPI to hold the RSA modulus. + * This may be \c NULL if this field need not be exported. + * \param P The MPI to hold the first prime factor of \p N. + * This may be \c NULL if this field need not be exported. + * \param Q The MPI to hold the second prime factor of \p N. + * This may be \c NULL if this field need not be exported. + * \param D The MPI to hold the private exponent. + * This may be \c NULL if this field need not be exported. + * \param E The MPI to hold the public exponent. + * This may be \c NULL if this field need not be exported. * * \return \c 0 on success. - * \return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION if exporting the + * \return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED if exporting the * requested parameters cannot be done due to missing * functionality or because of security policies. * \return A non-zero return code on any other failure. @@ -321,7 +332,7 @@ int mbedtls_rsa_export( const mbedtls_rsa_context *ctx, * zero Bytes. * * Possible reasons for returning - * #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION:<ul> + * #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED:<ul> * <li>An alternative RSA implementation is in use, which * stores the key externally, and either cannot or should * not export it into RAM.</li> @@ -336,21 +347,24 @@ int mbedtls_rsa_export( const mbedtls_rsa_context *ctx, * buffer pointers are NULL. * * \param ctx The initialized RSA context. - * \param N The Byte array to store the RSA modulus, or NULL. + * \param N The Byte array to store the RSA modulus, + * or \c NULL if this field need not be exported. * \param N_len The size of the buffer for the modulus. - * \param P The Byte array to hold the first prime factor of \p N, or - * NULL. + * \param P The Byte array to hold the first prime factor of \p N, + * or \c NULL if this field need not be exported. * \param P_len The size of the buffer for the first prime factor. - * \param Q The Byte array to hold the second prime factor of \p N, or - * NULL. + * \param Q The Byte array to hold the second prime factor of \p N, + * or \c NULL if this field need not be exported. * \param Q_len The size of the buffer for the second prime factor. - * \param D The Byte array to hold the private exponent, or NULL. + * \param D The Byte array to hold the private exponent, + * or \c NULL if this field need not be exported. * \param D_len The size of the buffer for the private exponent. - * \param E The Byte array to hold the public exponent, or NULL. + * \param E The Byte array to hold the public exponent, + * or \c NULL if this field need not be exported. * \param E_len The size of the buffer for the public exponent. * * \return \c 0 on success. - * \return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION if exporting the + * \return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED if exporting the * requested parameters cannot be done due to missing * functionality or because of security policies. * \return A non-zero return code on any other failure. @@ -370,9 +384,12 @@ int mbedtls_rsa_export_raw( const mbedtls_rsa_context *ctx, * mbedtls_rsa_deduce_opt(). * * \param ctx The initialized RSA context. - * \param DP The MPI to hold D modulo P-1, or NULL. - * \param DQ The MPI to hold D modulo Q-1, or NULL. - * \param QP The MPI to hold modular inverse of Q modulo P, or NULL. + * \param DP The MPI to hold \c D modulo `P-1`, + * or \c NULL if it need not be exported. + * \param DQ The MPI to hold \c D modulo `Q-1`, + * or \c NULL if it need not be exported. + * \param QP The MPI to hold modular inverse of \c Q modulo \c P, + * or \c NULL if it need not be exported. * * \return \c 0 on success. * \return A non-zero error code on failure. @@ -385,13 +402,13 @@ int mbedtls_rsa_export_crt( const mbedtls_rsa_context *ctx, * \brief This function sets padding for an already initialized RSA * context. See mbedtls_rsa_init() for details. * - * \param ctx The RSA context to be set. - * \param padding Selects padding mode: #MBEDTLS_RSA_PKCS_V15 or - * #MBEDTLS_RSA_PKCS_V21. + * \param ctx The initialized RSA context to be configured. + * \param padding The padding mode to use. This must be either + * #MBEDTLS_RSA_PKCS_V15 or #MBEDTLS_RSA_PKCS_V21. * \param hash_id The #MBEDTLS_RSA_PKCS_V21 hash identifier. */ void mbedtls_rsa_set_padding( mbedtls_rsa_context *ctx, int padding, - int hash_id); + int hash_id ); /** * \brief This function retrieves the length of RSA modulus in Bytes. @@ -409,11 +426,14 @@ size_t mbedtls_rsa_get_len( const mbedtls_rsa_context *ctx ); * \note mbedtls_rsa_init() must be called before this function, * to set up the RSA context. * - * \param ctx The RSA context used to hold the key. - * \param f_rng The RNG function. - * \param p_rng The RNG context. + * \param ctx The initialized RSA context used to hold the key. + * \param f_rng The RNG function to be used for key generation. + * This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. + * This may be \c NULL if \p f_rng doesn't need a context. * \param nbits The size of the public key in bits. - * \param exponent The public exponent. For example, 65537. + * \param exponent The public exponent to use. For example, \c 65537. + * This must be odd and greater than \c 1. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. @@ -431,7 +451,7 @@ int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx, * enough information is present to perform an RSA public key * operation using mbedtls_rsa_public(). * - * \param ctx The RSA context to check. + * \param ctx The initialized RSA context to check. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. @@ -470,7 +490,7 @@ int mbedtls_rsa_check_pubkey( const mbedtls_rsa_context *ctx ); * parameters, which goes beyond what is effectively checkable * by the library.</li></ul> * - * \param ctx The RSA context to check. + * \param ctx The initialized RSA context to check. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. @@ -482,8 +502,8 @@ int mbedtls_rsa_check_privkey( const mbedtls_rsa_context *ctx ); * * It checks each of the contexts, and makes sure they match. * - * \param pub The RSA context holding the public key. - * \param prv The RSA context holding the private key. + * \param pub The initialized RSA context holding the public key. + * \param prv The initialized RSA context holding the private key. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. @@ -494,18 +514,19 @@ int mbedtls_rsa_check_pub_priv( const mbedtls_rsa_context *pub, /** * \brief This function performs an RSA public key operation. * + * \param ctx The initialized RSA context to use. + * \param input The input buffer. This must be a readable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * \param output The output buffer. This must be a writable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * * \note This function does not handle message padding. * * \note Make sure to set \p input[0] = 0 or ensure that * input is smaller than \p N. * - * \note The input and output buffers must be large - * enough. For example, 128 Bytes if RSA-1024 is used. - * - * \param ctx The RSA context. - * \param input The input buffer. - * \param output The output buffer. - * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ @@ -516,9 +537,6 @@ int mbedtls_rsa_public( mbedtls_rsa_context *ctx, /** * \brief This function performs an RSA private key operation. * - * \note The input and output buffers must be large - * enough. For example, 128 Bytes if RSA-1024 is used. - * * \note Blinding is used if and only if a PRNG is provided. * * \note If blinding is used, both the base of exponentation @@ -530,11 +548,18 @@ int mbedtls_rsa_public( mbedtls_rsa_context *ctx, * Future versions of the library may enforce the presence * of a PRNG. * - * \param ctx The RSA context. - * \param f_rng The RNG function. Needed for blinding. - * \param p_rng The RNG context. - * \param input The input buffer. - * \param output The output buffer. + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function, used for blinding. It is discouraged + * and deprecated to pass \c NULL here, in which case + * blinding will be omitted. + * \param p_rng The RNG context to pass to \p f_rng. This may be \c NULL + * if \p f_rng is \c NULL or if \p f_rng doesn't need a context. + * \param input The input buffer. This must be a readable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * \param output The output buffer. This must be a writable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. @@ -553,9 +578,6 @@ int mbedtls_rsa_private( mbedtls_rsa_context *ctx, * It is the generic wrapper for performing a PKCS#1 encryption * operation using the \p mode from the context. * - * \note The input and output buffers must be as large as the size - * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. - * * \deprecated It is deprecated and discouraged to call this function * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library * are likely to remove the \p mode argument and have it @@ -563,16 +585,26 @@ int mbedtls_rsa_private( mbedtls_rsa_context *ctx, * * \note Alternative implementations of RSA need not support * mode being set to #MBEDTLS_RSA_PRIVATE and might instead - * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. - * - * \param ctx The RSA context. - * \param f_rng The RNG function. Needed for padding, PKCS#1 v2.1 - * encoding, and #MBEDTLS_RSA_PRIVATE. - * \param p_rng The RNG context. - * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. - * \param ilen The length of the plaintext. - * \param input The buffer holding the data to encrypt. - * \param output The buffer used to hold the ciphertext. + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG to use. It is mandatory for PKCS#1 v2.1 padding + * encoding, and for PKCS#1 v1.5 padding encoding when used + * with \p mode set to #MBEDTLS_RSA_PUBLIC. For PKCS#1 v1.5 + * padding encoding and \p mode set to #MBEDTLS_RSA_PRIVATE, + * it is used for blinding and should be provided in this + * case; see mbedtls_rsa_private() for more. + * \param p_rng The RNG context to be passed to \p f_rng. May be + * \c NULL if \p f_rng is \c NULL or if \p f_rng doesn't + * need a context argument. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE (deprecated). + * \param ilen The length of the plaintext in Bytes. + * \param input The input data to encrypt. This must be a readable + * buffer of size \p ilen Bytes. This must not be \c NULL. + * \param output The output buffer. This must be a writable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. @@ -588,9 +620,6 @@ int mbedtls_rsa_pkcs1_encrypt( mbedtls_rsa_context *ctx, * \brief This function performs a PKCS#1 v1.5 encryption operation * (RSAES-PKCS1-v1_5-ENCRYPT). * - * \note The output buffer must be as large as the size - * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. - * * \deprecated It is deprecated and discouraged to call this function * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library * are likely to remove the \p mode argument and have it @@ -598,16 +627,24 @@ int mbedtls_rsa_pkcs1_encrypt( mbedtls_rsa_context *ctx, * * \note Alternative implementations of RSA need not support * mode being set to #MBEDTLS_RSA_PRIVATE and might instead - * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. - * - * \param ctx The RSA context. - * \param f_rng The RNG function. Needed for padding and - * #MBEDTLS_RSA_PRIVATE. - * \param p_rng The RNG context. - * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. - * \param ilen The length of the plaintext. - * \param input The buffer holding the data to encrypt. - * \param output The buffer used to hold the ciphertext. + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function to use. It is needed for padding generation + * if \p mode is #MBEDTLS_RSA_PUBLIC. If \p mode is + * #MBEDTLS_RSA_PRIVATE (discouraged), it is used for + * blinding and should be provided; see mbedtls_rsa_private(). + * \param p_rng The RNG context to be passed to \p f_rng. This may + * be \c NULL if \p f_rng is \c NULL or if \p f_rng + * doesn't need a context argument. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE (deprecated). + * \param ilen The length of the plaintext in Bytes. + * \param input The input data to encrypt. This must be a readable + * buffer of size \p ilen Bytes. This must not be \c NULL. + * \param output The output buffer. This must be a writable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. @@ -633,18 +670,25 @@ int mbedtls_rsa_rsaes_pkcs1_v15_encrypt( mbedtls_rsa_context *ctx, * * \note Alternative implementations of RSA need not support * mode being set to #MBEDTLS_RSA_PRIVATE and might instead - * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. - * - * \param ctx The RSA context. - * \param f_rng The RNG function. Needed for padding and PKCS#1 v2.1 - * encoding and #MBEDTLS_RSA_PRIVATE. - * \param p_rng The RNG context. - * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initnialized RSA context to use. + * \param f_rng The RNG function to use. This is needed for padding + * generation and must be provided. + * \param p_rng The RNG context to be passed to \p f_rng. This may + * be \c NULL if \p f_rng doesn't need a context argument. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE (deprecated). * \param label The buffer holding the custom label to use. - * \param label_len The length of the label. - * \param ilen The length of the plaintext. - * \param input The buffer holding the data to encrypt. - * \param output The buffer used to hold the ciphertext. + * This must be a readable buffer of length \p label_len + * Bytes. It may be \c NULL if \p label_len is \c 0. + * \param label_len The length of the label in Bytes. + * \param ilen The length of the plaintext buffer \p input in Bytes. + * \param input The input data to encrypt. This must be a readable + * buffer of size \p ilen Bytes. This must not be \c NULL. + * \param output The output buffer. This must be a writable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. @@ -672,9 +716,6 @@ int mbedtls_rsa_rsaes_oaep_encrypt( mbedtls_rsa_context *ctx, * hold the decryption of the particular ciphertext provided, * the function returns \c MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE. * - * \note The input buffer must be as large as the size - * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. - * * \deprecated It is deprecated and discouraged to call this function * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library * are likely to remove the \p mode argument and have it @@ -682,16 +723,25 @@ int mbedtls_rsa_rsaes_oaep_encrypt( mbedtls_rsa_context *ctx, * * \note Alternative implementations of RSA need not support * mode being set to #MBEDTLS_RSA_PUBLIC and might instead - * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. - * - * \param ctx The RSA context. - * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE. - * \param p_rng The RNG context. - * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. - * \param olen The length of the plaintext. - * \param input The buffer holding the encrypted data. - * \param output The buffer used to hold the plaintext. - * \param output_max_len The maximum length of the output buffer. + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function. If \p mode is #MBEDTLS_RSA_PRIVATE, + * this is used for blinding and should be provided; see + * mbedtls_rsa_private() for more. If \p mode is + * #MBEDTLS_RSA_PUBLIC, it is ignored. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng is \c NULL or doesn't need a context. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PRIVATE or #MBEDTLS_RSA_PUBLIC (deprecated). + * \param olen The address at which to store the length of + * the plaintext. This must not be \c NULL. + * \param input The ciphertext buffer. This must be a readable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * \param output The buffer used to hold the plaintext. This must + * be a writable buffer of length \p output_max_len Bytes. + * \param output_max_len The length in Bytes of the output buffer \p output. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. @@ -715,9 +765,6 @@ int mbedtls_rsa_pkcs1_decrypt( mbedtls_rsa_context *ctx, * hold the decryption of the particular ciphertext provided, * the function returns #MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE. * - * \note The input buffer must be as large as the size - * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. - * * \deprecated It is deprecated and discouraged to call this function * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library * are likely to remove the \p mode argument and have it @@ -725,16 +772,25 @@ int mbedtls_rsa_pkcs1_decrypt( mbedtls_rsa_context *ctx, * * \note Alternative implementations of RSA need not support * mode being set to #MBEDTLS_RSA_PUBLIC and might instead - * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. - * - * \param ctx The RSA context. - * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE. - * \param p_rng The RNG context. - * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. - * \param olen The length of the plaintext. - * \param input The buffer holding the encrypted data. - * \param output The buffer to hold the plaintext. - * \param output_max_len The maximum length of the output buffer. + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function. If \p mode is #MBEDTLS_RSA_PRIVATE, + * this is used for blinding and should be provided; see + * mbedtls_rsa_private() for more. If \p mode is + * #MBEDTLS_RSA_PUBLIC, it is ignored. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng is \c NULL or doesn't need a context. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PRIVATE or #MBEDTLS_RSA_PUBLIC (deprecated). + * \param olen The address at which to store the length of + * the plaintext. This must not be \c NULL. + * \param input The ciphertext buffer. This must be a readable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * \param output The buffer used to hold the plaintext. This must + * be a writable buffer of length \p output_max_len Bytes. + * \param output_max_len The length in Bytes of the output buffer \p output. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. @@ -760,9 +816,6 @@ int mbedtls_rsa_rsaes_pkcs1_v15_decrypt( mbedtls_rsa_context *ctx, * ciphertext provided, the function returns * #MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE. * - * \note The input buffer must be as large as the size - * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. - * * \deprecated It is deprecated and discouraged to call this function * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library * are likely to remove the \p mode argument and have it @@ -770,18 +823,29 @@ int mbedtls_rsa_rsaes_pkcs1_v15_decrypt( mbedtls_rsa_context *ctx, * * \note Alternative implementations of RSA need not support * mode being set to #MBEDTLS_RSA_PUBLIC and might instead - * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. - * - * \param ctx The RSA context. - * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE. - * \param p_rng The RNG context. - * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function. If \p mode is #MBEDTLS_RSA_PRIVATE, + * this is used for blinding and should be provided; see + * mbedtls_rsa_private() for more. If \p mode is + * #MBEDTLS_RSA_PUBLIC, it is ignored. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng is \c NULL or doesn't need a context. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PRIVATE or #MBEDTLS_RSA_PUBLIC (deprecated). * \param label The buffer holding the custom label to use. - * \param label_len The length of the label. - * \param olen The length of the plaintext. - * \param input The buffer holding the encrypted data. - * \param output The buffer to hold the plaintext. - * \param output_max_len The maximum length of the output buffer. + * This must be a readable buffer of length \p label_len + * Bytes. It may be \c NULL if \p label_len is \c 0. + * \param label_len The length of the label in Bytes. + * \param olen The address at which to store the length of + * the plaintext. This must not be \c NULL. + * \param input The ciphertext buffer. This must be a readable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * \param output The buffer used to hold the plaintext. This must + * be a writable buffer of length \p output_max_len Bytes. + * \param output_max_len The length in Bytes of the output buffer \p output. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. @@ -817,18 +881,30 @@ int mbedtls_rsa_rsaes_oaep_decrypt( mbedtls_rsa_context *ctx, * * \note Alternative implementations of RSA need not support * mode being set to #MBEDTLS_RSA_PUBLIC and might instead - * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. - * - * \param ctx The RSA context. - * \param f_rng The RNG function. Needed for PKCS#1 v2.1 encoding and for - * #MBEDTLS_RSA_PRIVATE. - * \param p_rng The RNG context. - * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function to use. If the padding mode is PKCS#1 v2.1, + * this must be provided. If the padding mode is PKCS#1 v1.5 and + * \p mode is #MBEDTLS_RSA_PRIVATE, it is used for blinding + * and should be provided; see mbedtls_rsa_private() for more + * more. It is ignored otherwise. + * \param p_rng The RNG context to be passed to \p f_rng. This may be \c NULL + * if \p f_rng is \c NULL or doesn't need a context argument. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PRIVATE or #MBEDTLS_RSA_PUBLIC (deprecated). * \param md_alg The message-digest algorithm used to hash the original data. * Use #MBEDTLS_MD_NONE for signing raw data. - * \param hashlen The length of the message digest. Only used if \p md_alg is #MBEDTLS_MD_NONE. - * \param hash The buffer holding the message digest. - * \param sig The buffer to hold the ciphertext. + * \param hashlen The length of the message digest. + * Ths is only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest or raw data. + * If \p md_alg is #MBEDTLS_MD_NONE, this must be a readable + * buffer of length \p hashlen Bytes. If \p md_alg is not + * #MBEDTLS_MD_NONE, it must be a readable buffer of length + * the size of the hash corresponding to \p md_alg. + * \param sig The buffer to hold the signature. This must be a writable + * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. * * \return \c 0 if the signing operation was successful. * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. @@ -846,9 +922,6 @@ int mbedtls_rsa_pkcs1_sign( mbedtls_rsa_context *ctx, * \brief This function performs a PKCS#1 v1.5 signature * operation (RSASSA-PKCS1-v1_5-SIGN). * - * \note The \p sig buffer must be as large as the size - * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. - * * \deprecated It is deprecated and discouraged to call this function * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library * are likely to remove the \p mode argument and have it @@ -856,17 +929,29 @@ int mbedtls_rsa_pkcs1_sign( mbedtls_rsa_context *ctx, * * \note Alternative implementations of RSA need not support * mode being set to #MBEDTLS_RSA_PUBLIC and might instead - * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. - * - * \param ctx The RSA context. - * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE. - * \param p_rng The RNG context. - * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function. If \p mode is #MBEDTLS_RSA_PRIVATE, + * this is used for blinding and should be provided; see + * mbedtls_rsa_private() for more. If \p mode is + * #MBEDTLS_RSA_PUBLIC, it is ignored. + * \param p_rng The RNG context to be passed to \p f_rng. This may be \c NULL + * if \p f_rng is \c NULL or doesn't need a context argument. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PRIVATE or #MBEDTLS_RSA_PUBLIC (deprecated). * \param md_alg The message-digest algorithm used to hash the original data. * Use #MBEDTLS_MD_NONE for signing raw data. - * \param hashlen The length of the message digest. Only used if \p md_alg is #MBEDTLS_MD_NONE. - * \param hash The buffer holding the message digest. - * \param sig The buffer to hold the ciphertext. + * \param hashlen The length of the message digest. + * Ths is only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest or raw data. + * If \p md_alg is #MBEDTLS_MD_NONE, this must be a readable + * buffer of length \p hashlen Bytes. If \p md_alg is not + * #MBEDTLS_MD_NONE, it must be a readable buffer of length + * the size of the hash corresponding to \p md_alg. + * \param sig The buffer to hold the signature. This must be a writable + * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. * * \return \c 0 if the signing operation was successful. * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. @@ -884,9 +969,6 @@ int mbedtls_rsa_rsassa_pkcs1_v15_sign( mbedtls_rsa_context *ctx, * \brief This function performs a PKCS#1 v2.1 PSS signature * operation (RSASSA-PSS-SIGN). * - * \note The \p sig buffer must be as large as the size - * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. - * * \note The \p hash_id in the RSA context is the one used for the * encoding. \p md_alg in the function call is the type of hash * that is encoded. According to <em>RFC-3447: Public-Key @@ -894,6 +976,16 @@ int mbedtls_rsa_rsassa_pkcs1_v15_sign( mbedtls_rsa_context *ctx, * Specifications</em> it is advised to keep both hashes the * same. * + * \note This function always uses the maximum possible salt size, + * up to the length of the payload hash. This choice of salt + * size complies with FIPS 186-4 §5.5 (e) and RFC 8017 (PKCS#1 + * v2.2) §9.1.1 step 3. Furthermore this function enforces a + * minimum salt size which is the hash size minus 2 bytes. If + * this minimum size is too large given the key size (the salt + * size, plus the hash size, plus 2 bytes must be no more than + * the key size in bytes), this function returns + * #MBEDTLS_ERR_RSA_BAD_INPUT_DATA. + * * \deprecated It is deprecated and discouraged to call this function * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library * are likely to remove the \p mode argument and have it @@ -901,18 +993,26 @@ int mbedtls_rsa_rsassa_pkcs1_v15_sign( mbedtls_rsa_context *ctx, * * \note Alternative implementations of RSA need not support * mode being set to #MBEDTLS_RSA_PUBLIC and might instead - * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. - * - * \param ctx The RSA context. - * \param f_rng The RNG function. Needed for PKCS#1 v2.1 encoding and for - * #MBEDTLS_RSA_PRIVATE. - * \param p_rng The RNG context. - * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function. It must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be \c NULL + * if \p f_rng doesn't need a context argument. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PRIVATE or #MBEDTLS_RSA_PUBLIC (deprecated). * \param md_alg The message-digest algorithm used to hash the original data. * Use #MBEDTLS_MD_NONE for signing raw data. - * \param hashlen The length of the message digest. Only used if \p md_alg is #MBEDTLS_MD_NONE. - * \param hash The buffer holding the message digest. - * \param sig The buffer to hold the ciphertext. + * \param hashlen The length of the message digest. + * Ths is only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest or raw data. + * If \p md_alg is #MBEDTLS_MD_NONE, this must be a readable + * buffer of length \p hashlen Bytes. If \p md_alg is not + * #MBEDTLS_MD_NONE, it must be a readable buffer of length + * the size of the hash corresponding to \p md_alg. + * \param sig The buffer to hold the signature. This must be a writable + * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. * * \return \c 0 if the signing operation was successful. * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. @@ -933,9 +1033,6 @@ int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx, * This is the generic wrapper for performing a PKCS#1 * verification using the mode from the context. * - * \note The \p sig buffer must be as large as the size - * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. - * * \note For PKCS#1 v2.1 encoding, see comments on * mbedtls_rsa_rsassa_pss_verify() about \p md_alg and * \p hash_id. @@ -947,17 +1044,28 @@ int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx, * * \note Alternative implementations of RSA need not support * mode being set to #MBEDTLS_RSA_PRIVATE and might instead - * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. - * - * \param ctx The RSA public key context. - * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE. - * \param p_rng The RNG context. - * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initialized RSA public key context to use. + * \param f_rng The RNG function to use. If \p mode is #MBEDTLS_RSA_PRIVATE, + * this is used for blinding and should be provided; see + * mbedtls_rsa_private() for more. Otherwise, it is ignored. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng is \c NULL or doesn't need a context. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE (deprecated). * \param md_alg The message-digest algorithm used to hash the original data. * Use #MBEDTLS_MD_NONE for signing raw data. - * \param hashlen The length of the message digest. Only used if \p md_alg is #MBEDTLS_MD_NONE. - * \param hash The buffer holding the message digest. - * \param sig The buffer holding the ciphertext. + * \param hashlen The length of the message digest. + * This is only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest or raw data. + * If \p md_alg is #MBEDTLS_MD_NONE, this must be a readable + * buffer of length \p hashlen Bytes. If \p md_alg is not + * #MBEDTLS_MD_NONE, it must be a readable buffer of length + * the size of the hash corresponding to \p md_alg. + * \param sig The buffer holding the signature. This must be a readable + * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. * * \return \c 0 if the verify operation was successful. * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. @@ -975,9 +1083,6 @@ int mbedtls_rsa_pkcs1_verify( mbedtls_rsa_context *ctx, * \brief This function performs a PKCS#1 v1.5 verification * operation (RSASSA-PKCS1-v1_5-VERIFY). * - * \note The \p sig buffer must be as large as the size - * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. - * * \deprecated It is deprecated and discouraged to call this function * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library * are likely to remove the \p mode argument and have it @@ -985,17 +1090,28 @@ int mbedtls_rsa_pkcs1_verify( mbedtls_rsa_context *ctx, * * \note Alternative implementations of RSA need not support * mode being set to #MBEDTLS_RSA_PRIVATE and might instead - * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. - * - * \param ctx The RSA public key context. - * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE. - * \param p_rng The RNG context. - * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initialized RSA public key context to use. + * \param f_rng The RNG function to use. If \p mode is #MBEDTLS_RSA_PRIVATE, + * this is used for blinding and should be provided; see + * mbedtls_rsa_private() for more. Otherwise, it is ignored. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng is \c NULL or doesn't need a context. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE (deprecated). * \param md_alg The message-digest algorithm used to hash the original data. * Use #MBEDTLS_MD_NONE for signing raw data. - * \param hashlen The length of the message digest. Only used if \p md_alg is #MBEDTLS_MD_NONE. - * \param hash The buffer holding the message digest. - * \param sig The buffer holding the ciphertext. + * \param hashlen The length of the message digest. + * This is only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest or raw data. + * If \p md_alg is #MBEDTLS_MD_NONE, this must be a readable + * buffer of length \p hashlen Bytes. If \p md_alg is not + * #MBEDTLS_MD_NONE, it must be a readable buffer of length + * the size of the hash corresponding to \p md_alg. + * \param sig The buffer holding the signature. This must be a readable + * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. * * \return \c 0 if the verify operation was successful. * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. @@ -1016,9 +1132,6 @@ int mbedtls_rsa_rsassa_pkcs1_v15_verify( mbedtls_rsa_context *ctx, * The hash function for the MGF mask generating function * is that specified in the RSA context. * - * \note The \p sig buffer must be as large as the size - * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. - * * \note The \p hash_id in the RSA context is the one used for the * verification. \p md_alg in the function call is the type of * hash that is verified. According to <em>RFC-3447: Public-Key @@ -1034,17 +1147,28 @@ int mbedtls_rsa_rsassa_pkcs1_v15_verify( mbedtls_rsa_context *ctx, * * \note Alternative implementations of RSA need not support * mode being set to #MBEDTLS_RSA_PRIVATE and might instead - * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. - * - * \param ctx The RSA public key context. - * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE. - * \param p_rng The RNG context. - * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initialized RSA public key context to use. + * \param f_rng The RNG function to use. If \p mode is #MBEDTLS_RSA_PRIVATE, + * this is used for blinding and should be provided; see + * mbedtls_rsa_private() for more. Otherwise, it is ignored. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng is \c NULL or doesn't need a context. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE (deprecated). * \param md_alg The message-digest algorithm used to hash the original data. * Use #MBEDTLS_MD_NONE for signing raw data. - * \param hashlen The length of the message digest. Only used if \p md_alg is #MBEDTLS_MD_NONE. - * \param hash The buffer holding the message digest. - * \param sig The buffer holding the ciphertext. + * \param hashlen The length of the message digest. + * This is only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest or raw data. + * If \p md_alg is #MBEDTLS_MD_NONE, this must be a readable + * buffer of length \p hashlen Bytes. If \p md_alg is not + * #MBEDTLS_MD_NONE, it must be a readable buffer of length + * the size of the hash corresponding to \p md_alg. + * \param sig The buffer holding the signature. This must be a readable + * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. * * \return \c 0 if the verify operation was successful. * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. @@ -1070,19 +1194,29 @@ int mbedtls_rsa_rsassa_pss_verify( mbedtls_rsa_context *ctx, * * \note The \p hash_id in the RSA context is ignored. * - * \param ctx The RSA public key context. - * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE. - * \param p_rng The RNG context. - * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param ctx The initialized RSA public key context to use. + * \param f_rng The RNG function to use. If \p mode is #MBEDTLS_RSA_PRIVATE, + * this is used for blinding and should be provided; see + * mbedtls_rsa_private() for more. Otherwise, it is ignored. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng is \c NULL or doesn't need a context. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. * \param md_alg The message-digest algorithm used to hash the original data. * Use #MBEDTLS_MD_NONE for signing raw data. - * \param hashlen The length of the message digest. Only used if \p md_alg is - * #MBEDTLS_MD_NONE. - * \param hash The buffer holding the message digest. - * \param mgf1_hash_id The message digest used for mask generation. - * \param expected_salt_len The length of the salt used in padding. Use - * #MBEDTLS_RSA_SALT_LEN_ANY to accept any salt length. - * \param sig The buffer holding the ciphertext. + * \param hashlen The length of the message digest. + * This is only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest or raw data. + * If \p md_alg is #MBEDTLS_MD_NONE, this must be a readable + * buffer of length \p hashlen Bytes. If \p md_alg is not + * #MBEDTLS_MD_NONE, it must be a readable buffer of length + * the size of the hash corresponding to \p md_alg. + * \param mgf1_hash_id The message digest used for mask generation. + * \param expected_salt_len The length of the salt used in padding. Use + * #MBEDTLS_RSA_SALT_LEN_ANY to accept any salt length. + * \param sig The buffer holding the signature. This must be a readable + * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. * * \return \c 0 if the verify operation was successful. * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. @@ -1101,8 +1235,8 @@ int mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_rsa_context *ctx, /** * \brief This function copies the components of an RSA context. * - * \param dst The destination context. - * \param src The source context. + * \param dst The destination context. This must be initialized. + * \param src The source context. This must be initialized. * * \return \c 0 on success. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory allocation failure. @@ -1112,7 +1246,9 @@ int mbedtls_rsa_copy( mbedtls_rsa_context *dst, const mbedtls_rsa_context *src ) /** * \brief This function frees the components of an RSA key. * - * \param ctx The RSA Context to free. + * \param ctx The RSA context to free. May be \c NULL, in which case + * this function is a no-op. If it is not \c NULL, it must + * point to an initialized RSA context. */ void mbedtls_rsa_free( mbedtls_rsa_context *ctx ); diff --git a/thirdparty/mbedtls/include/mbedtls/sha1.h b/thirdparty/mbedtls/include/mbedtls/sha1.h index 65a124c94b..38ea10b137 100644 --- a/thirdparty/mbedtls/include/mbedtls/sha1.h +++ b/thirdparty/mbedtls/include/mbedtls/sha1.h @@ -40,7 +40,9 @@ #include <stddef.h> #include <stdint.h> +/* MBEDTLS_ERR_SHA1_HW_ACCEL_FAILED is deprecated and should not be used. */ #define MBEDTLS_ERR_SHA1_HW_ACCEL_FAILED -0x0035 /**< SHA-1 hardware accelerator failed */ +#define MBEDTLS_ERR_SHA1_BAD_INPUT_DATA -0x0073 /**< SHA-1 input data was malformed. */ #ifdef __cplusplus extern "C" { @@ -58,7 +60,7 @@ extern "C" { * stronger message digests instead. * */ -typedef struct +typedef struct mbedtls_sha1_context { uint32_t total[2]; /*!< The number of Bytes processed. */ uint32_t state[5]; /*!< The intermediate digest state. */ @@ -78,6 +80,7 @@ mbedtls_sha1_context; * stronger message digests instead. * * \param ctx The SHA-1 context to initialize. + * This must not be \c NULL. * */ void mbedtls_sha1_init( mbedtls_sha1_context *ctx ); @@ -89,7 +92,10 @@ void mbedtls_sha1_init( mbedtls_sha1_context *ctx ); * constitutes a security risk. We recommend considering * stronger message digests instead. * - * \param ctx The SHA-1 context to clear. + * \param ctx The SHA-1 context to clear. This may be \c NULL, + * in which case this function does nothing. If it is + * not \c NULL, it must point to an initialized + * SHA-1 context. * */ void mbedtls_sha1_free( mbedtls_sha1_context *ctx ); @@ -101,8 +107,8 @@ void mbedtls_sha1_free( mbedtls_sha1_context *ctx ); * constitutes a security risk. We recommend considering * stronger message digests instead. * - * \param dst The SHA-1 context to clone to. - * \param src The SHA-1 context to clone from. + * \param dst The SHA-1 context to clone to. This must be initialized. + * \param src The SHA-1 context to clone from. This must be initialized. * */ void mbedtls_sha1_clone( mbedtls_sha1_context *dst, @@ -115,9 +121,10 @@ void mbedtls_sha1_clone( mbedtls_sha1_context *dst, * constitutes a security risk. We recommend considering * stronger message digests instead. * - * \param ctx The SHA-1 context to initialize. + * \param ctx The SHA-1 context to initialize. This must be initialized. * * \return \c 0 on success. + * \return A negative error code on failure. * */ int mbedtls_sha1_starts_ret( mbedtls_sha1_context *ctx ); @@ -130,11 +137,14 @@ int mbedtls_sha1_starts_ret( mbedtls_sha1_context *ctx ); * constitutes a security risk. We recommend considering * stronger message digests instead. * - * \param ctx The SHA-1 context. + * \param ctx The SHA-1 context. This must be initialized + * and have a hash operation started. * \param input The buffer holding the input data. - * \param ilen The length of the input data. + * This must be a readable buffer of length \p ilen Bytes. + * \param ilen The length of the input data \p input in Bytes. * * \return \c 0 on success. + * \return A negative error code on failure. */ int mbedtls_sha1_update_ret( mbedtls_sha1_context *ctx, const unsigned char *input, @@ -148,10 +158,13 @@ int mbedtls_sha1_update_ret( mbedtls_sha1_context *ctx, * constitutes a security risk. We recommend considering * stronger message digests instead. * - * \param ctx The SHA-1 context. - * \param output The SHA-1 checksum result. + * \param ctx The SHA-1 context to use. This must be initialized and + * have a hash operation started. + * \param output The SHA-1 checksum result. This must be a writable + * buffer of length \c 20 Bytes. * * \return \c 0 on success. + * \return A negative error code on failure. */ int mbedtls_sha1_finish_ret( mbedtls_sha1_context *ctx, unsigned char output[20] ); @@ -163,10 +176,12 @@ int mbedtls_sha1_finish_ret( mbedtls_sha1_context *ctx, * constitutes a security risk. We recommend considering * stronger message digests instead. * - * \param ctx The SHA-1 context. - * \param data The data block being processed. + * \param ctx The SHA-1 context to use. This must be initialized. + * \param data The data block being processed. This must be a + * readable buffer of length \c 64 Bytes. * * \return \c 0 on success. + * \return A negative error code on failure. * */ int mbedtls_internal_sha1_process( mbedtls_sha1_context *ctx, @@ -187,7 +202,7 @@ int mbedtls_internal_sha1_process( mbedtls_sha1_context *ctx, * * \deprecated Superseded by mbedtls_sha1_starts_ret() in 2.7.0. * - * \param ctx The SHA-1 context to initialize. + * \param ctx The SHA-1 context to initialize. This must be initialized. * */ MBEDTLS_DEPRECATED void mbedtls_sha1_starts( mbedtls_sha1_context *ctx ); @@ -202,9 +217,11 @@ MBEDTLS_DEPRECATED void mbedtls_sha1_starts( mbedtls_sha1_context *ctx ); * * \deprecated Superseded by mbedtls_sha1_update_ret() in 2.7.0. * - * \param ctx The SHA-1 context. + * \param ctx The SHA-1 context. This must be initialized and + * have a hash operation started. * \param input The buffer holding the input data. - * \param ilen The length of the input data. + * This must be a readable buffer of length \p ilen Bytes. + * \param ilen The length of the input data \p input in Bytes. * */ MBEDTLS_DEPRECATED void mbedtls_sha1_update( mbedtls_sha1_context *ctx, @@ -221,9 +238,10 @@ MBEDTLS_DEPRECATED void mbedtls_sha1_update( mbedtls_sha1_context *ctx, * * \deprecated Superseded by mbedtls_sha1_finish_ret() in 2.7.0. * - * \param ctx The SHA-1 context. + * \param ctx The SHA-1 context. This must be initialized and + * have a hash operation started. * \param output The SHA-1 checksum result. - * + * This must be a writable buffer of length \c 20 Bytes. */ MBEDTLS_DEPRECATED void mbedtls_sha1_finish( mbedtls_sha1_context *ctx, unsigned char output[20] ); @@ -237,8 +255,9 @@ MBEDTLS_DEPRECATED void mbedtls_sha1_finish( mbedtls_sha1_context *ctx, * * \deprecated Superseded by mbedtls_internal_sha1_process() in 2.7.0. * - * \param ctx The SHA-1 context. + * \param ctx The SHA-1 context. This must be initialized. * \param data The data block being processed. + * This must be a readable buffer of length \c 64 bytes. * */ MBEDTLS_DEPRECATED void mbedtls_sha1_process( mbedtls_sha1_context *ctx, @@ -261,10 +280,13 @@ MBEDTLS_DEPRECATED void mbedtls_sha1_process( mbedtls_sha1_context *ctx, * stronger message digests instead. * * \param input The buffer holding the input data. - * \param ilen The length of the input data. + * This must be a readable buffer of length \p ilen Bytes. + * \param ilen The length of the input data \p input in Bytes. * \param output The SHA-1 checksum result. + * This must be a writable buffer of length \c 20 Bytes. * * \return \c 0 on success. + * \return A negative error code on failure. * */ int mbedtls_sha1_ret( const unsigned char *input, @@ -293,8 +315,10 @@ int mbedtls_sha1_ret( const unsigned char *input, * \deprecated Superseded by mbedtls_sha1_ret() in 2.7.0 * * \param input The buffer holding the input data. - * \param ilen The length of the input data. - * \param output The SHA-1 checksum result. + * This must be a readable buffer of length \p ilen Bytes. + * \param ilen The length of the input data \p input in Bytes. + * \param output The SHA-1 checksum result. This must be a writable + * buffer of size \c 20 Bytes. * */ MBEDTLS_DEPRECATED void mbedtls_sha1( const unsigned char *input, diff --git a/thirdparty/mbedtls/include/mbedtls/sha256.h b/thirdparty/mbedtls/include/mbedtls/sha256.h index adf31a82ed..0e42f0abba 100644 --- a/thirdparty/mbedtls/include/mbedtls/sha256.h +++ b/thirdparty/mbedtls/include/mbedtls/sha256.h @@ -36,7 +36,9 @@ #include <stddef.h> #include <stdint.h> +/* MBEDTLS_ERR_SHA256_HW_ACCEL_FAILED is deprecated and should not be used. */ #define MBEDTLS_ERR_SHA256_HW_ACCEL_FAILED -0x0037 /**< SHA-256 hardware accelerator failed */ +#define MBEDTLS_ERR_SHA256_BAD_INPUT_DATA -0x0074 /**< SHA-256 input data was malformed. */ #ifdef __cplusplus extern "C" { @@ -53,7 +55,7 @@ extern "C" { * checksum calculations. The choice between these two is * made in the call to mbedtls_sha256_starts_ret(). */ -typedef struct +typedef struct mbedtls_sha256_context { uint32_t total[2]; /*!< The number of Bytes processed. */ uint32_t state[8]; /*!< The intermediate digest state. */ @@ -70,22 +72,24 @@ mbedtls_sha256_context; /** * \brief This function initializes a SHA-256 context. * - * \param ctx The SHA-256 context to initialize. + * \param ctx The SHA-256 context to initialize. This must not be \c NULL. */ void mbedtls_sha256_init( mbedtls_sha256_context *ctx ); /** * \brief This function clears a SHA-256 context. * - * \param ctx The SHA-256 context to clear. + * \param ctx The SHA-256 context to clear. This may be \c NULL, in which + * case this function returns immediately. If it is not \c NULL, + * it must point to an initialized SHA-256 context. */ void mbedtls_sha256_free( mbedtls_sha256_context *ctx ); /** * \brief This function clones the state of a SHA-256 context. * - * \param dst The destination context. - * \param src The context to clone. + * \param dst The destination context. This must be initialized. + * \param src The context to clone. This must be initialized. */ void mbedtls_sha256_clone( mbedtls_sha256_context *dst, const mbedtls_sha256_context *src ); @@ -94,11 +98,12 @@ void mbedtls_sha256_clone( mbedtls_sha256_context *dst, * \brief This function starts a SHA-224 or SHA-256 checksum * calculation. * - * \param ctx The context to initialize. - * \param is224 Determines which function to use: - * 0: Use SHA-256, or 1: Use SHA-224. + * \param ctx The context to use. This must be initialized. + * \param is224 This determines which function to use. This must be + * either \c 0 for SHA-256, or \c 1 for SHA-224. * * \return \c 0 on success. + * \return A negative error code on failure. */ int mbedtls_sha256_starts_ret( mbedtls_sha256_context *ctx, int is224 ); @@ -106,11 +111,14 @@ int mbedtls_sha256_starts_ret( mbedtls_sha256_context *ctx, int is224 ); * \brief This function feeds an input buffer into an ongoing * SHA-256 checksum calculation. * - * \param ctx The SHA-256 context. - * \param input The buffer holding the data. - * \param ilen The length of the input data. + * \param ctx The SHA-256 context. This must be initialized + * and have a hash operation started. + * \param input The buffer holding the data. This must be a readable + * buffer of length \p ilen Bytes. + * \param ilen The length of the input data in Bytes. * * \return \c 0 on success. + * \return A negative error code on failure. */ int mbedtls_sha256_update_ret( mbedtls_sha256_context *ctx, const unsigned char *input, @@ -120,10 +128,13 @@ int mbedtls_sha256_update_ret( mbedtls_sha256_context *ctx, * \brief This function finishes the SHA-256 operation, and writes * the result to the output buffer. * - * \param ctx The SHA-256 context. + * \param ctx The SHA-256 context. This must be initialized + * and have a hash operation started. * \param output The SHA-224 or SHA-256 checksum result. + * This must be a writable buffer of length \c 32 Bytes. * * \return \c 0 on success. + * \return A negative error code on failure. */ int mbedtls_sha256_finish_ret( mbedtls_sha256_context *ctx, unsigned char output[32] ); @@ -133,10 +144,12 @@ int mbedtls_sha256_finish_ret( mbedtls_sha256_context *ctx, * the ongoing SHA-256 computation. This function is for * internal use only. * - * \param ctx The SHA-256 context. - * \param data The buffer holding one block of data. + * \param ctx The SHA-256 context. This must be initialized. + * \param data The buffer holding one block of data. This must + * be a readable buffer of length \c 64 Bytes. * * \return \c 0 on success. + * \return A negative error code on failure. */ int mbedtls_internal_sha256_process( mbedtls_sha256_context *ctx, const unsigned char data[64] ); @@ -151,12 +164,11 @@ int mbedtls_internal_sha256_process( mbedtls_sha256_context *ctx, * \brief This function starts a SHA-224 or SHA-256 checksum * calculation. * - * * \deprecated Superseded by mbedtls_sha256_starts_ret() in 2.7.0. * - * \param ctx The context to initialize. - * \param is224 Determines which function to use: - * 0: Use SHA-256, or 1: Use SHA-224. + * \param ctx The context to use. This must be initialized. + * \param is224 Determines which function to use. This must be + * either \c 0 for SHA-256, or \c 1 for SHA-224. */ MBEDTLS_DEPRECATED void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, int is224 ); @@ -167,9 +179,11 @@ MBEDTLS_DEPRECATED void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, * * \deprecated Superseded by mbedtls_sha256_update_ret() in 2.7.0. * - * \param ctx The SHA-256 context to initialize. - * \param input The buffer holding the data. - * \param ilen The length of the input data. + * \param ctx The SHA-256 context to use. This must be + * initialized and have a hash operation started. + * \param input The buffer holding the data. This must be a readable + * buffer of length \p ilen Bytes. + * \param ilen The length of the input data in Bytes. */ MBEDTLS_DEPRECATED void mbedtls_sha256_update( mbedtls_sha256_context *ctx, const unsigned char *input, @@ -181,8 +195,10 @@ MBEDTLS_DEPRECATED void mbedtls_sha256_update( mbedtls_sha256_context *ctx, * * \deprecated Superseded by mbedtls_sha256_finish_ret() in 2.7.0. * - * \param ctx The SHA-256 context. - * \param output The SHA-224 or SHA-256 checksum result. + * \param ctx The SHA-256 context. This must be initialized and + * have a hash operation started. + * \param output The SHA-224 or SHA-256 checksum result. This must be + * a writable buffer of length \c 32 Bytes. */ MBEDTLS_DEPRECATED void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, unsigned char output[32] ); @@ -194,8 +210,9 @@ MBEDTLS_DEPRECATED void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, * * \deprecated Superseded by mbedtls_internal_sha256_process() in 2.7.0. * - * \param ctx The SHA-256 context. - * \param data The buffer holding one block of data. + * \param ctx The SHA-256 context. This must be initialized. + * \param data The buffer holding one block of data. This must be + * a readable buffer of size \c 64 Bytes. */ MBEDTLS_DEPRECATED void mbedtls_sha256_process( mbedtls_sha256_context *ctx, const unsigned char data[64] ); @@ -213,11 +230,13 @@ MBEDTLS_DEPRECATED void mbedtls_sha256_process( mbedtls_sha256_context *ctx, * The SHA-256 result is calculated as * output = SHA-256(input buffer). * - * \param input The buffer holding the input data. - * \param ilen The length of the input data. - * \param output The SHA-224 or SHA-256 checksum result. - * \param is224 Determines which function to use: - * 0: Use SHA-256, or 1: Use SHA-224. + * \param input The buffer holding the data. This must be a readable + * buffer of length \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + * \param output The SHA-224 or SHA-256 checksum result. This must + * be a writable buffer of length \c 32 Bytes. + * \param is224 Determines which function to use. This must be + * either \c 0 for SHA-256, or \c 1 for SHA-224. */ int mbedtls_sha256_ret( const unsigned char *input, size_t ilen, @@ -243,11 +262,13 @@ int mbedtls_sha256_ret( const unsigned char *input, * * \deprecated Superseded by mbedtls_sha256_ret() in 2.7.0. * - * \param input The buffer holding the data. - * \param ilen The length of the input data. - * \param output The SHA-224 or SHA-256 checksum result. - * \param is224 Determines which function to use: - * 0: Use SHA-256, or 1: Use SHA-224. + * \param input The buffer holding the data. This must be a readable + * buffer of length \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + * \param output The SHA-224 or SHA-256 checksum result. This must be + * a writable buffer of length \c 32 Bytes. + * \param is224 Determines which function to use. This must be either + * \c 0 for SHA-256, or \c 1 for SHA-224. */ MBEDTLS_DEPRECATED void mbedtls_sha256( const unsigned char *input, size_t ilen, diff --git a/thirdparty/mbedtls/include/mbedtls/sha512.h b/thirdparty/mbedtls/include/mbedtls/sha512.h index 5bb83f43bd..7b26cf5cc3 100644 --- a/thirdparty/mbedtls/include/mbedtls/sha512.h +++ b/thirdparty/mbedtls/include/mbedtls/sha512.h @@ -35,7 +35,9 @@ #include <stddef.h> #include <stdint.h> +/* MBEDTLS_ERR_SHA512_HW_ACCEL_FAILED is deprecated and should not be used. */ #define MBEDTLS_ERR_SHA512_HW_ACCEL_FAILED -0x0039 /**< SHA-512 hardware accelerator failed */ +#define MBEDTLS_ERR_SHA512_BAD_INPUT_DATA -0x0075 /**< SHA-512 input data was malformed. */ #ifdef __cplusplus extern "C" { @@ -52,7 +54,7 @@ extern "C" { * checksum calculations. The choice between these two is * made in the call to mbedtls_sha512_starts_ret(). */ -typedef struct +typedef struct mbedtls_sha512_context { uint64_t total[2]; /*!< The number of Bytes processed. */ uint64_t state[8]; /*!< The intermediate digest state. */ @@ -69,22 +71,26 @@ mbedtls_sha512_context; /** * \brief This function initializes a SHA-512 context. * - * \param ctx The SHA-512 context to initialize. + * \param ctx The SHA-512 context to initialize. This must + * not be \c NULL. */ void mbedtls_sha512_init( mbedtls_sha512_context *ctx ); /** * \brief This function clears a SHA-512 context. * - * \param ctx The SHA-512 context to clear. + * \param ctx The SHA-512 context to clear. This may be \c NULL, + * in which case this function does nothing. If it + * is not \c NULL, it must point to an initialized + * SHA-512 context. */ void mbedtls_sha512_free( mbedtls_sha512_context *ctx ); /** * \brief This function clones the state of a SHA-512 context. * - * \param dst The destination context. - * \param src The context to clone. + * \param dst The destination context. This must be initialized. + * \param src The context to clone. This must be initialized. */ void mbedtls_sha512_clone( mbedtls_sha512_context *dst, const mbedtls_sha512_context *src ); @@ -93,11 +99,12 @@ void mbedtls_sha512_clone( mbedtls_sha512_context *dst, * \brief This function starts a SHA-384 or SHA-512 checksum * calculation. * - * \param ctx The SHA-512 context to initialize. - * \param is384 Determines which function to use: - * 0: Use SHA-512, or 1: Use SHA-384. + * \param ctx The SHA-512 context to use. This must be initialized. + * \param is384 Determines which function to use. This must be + * either \c for SHA-512, or \c 1 for SHA-384. * * \return \c 0 on success. + * \return A negative error code on failure. */ int mbedtls_sha512_starts_ret( mbedtls_sha512_context *ctx, int is384 ); @@ -105,11 +112,14 @@ int mbedtls_sha512_starts_ret( mbedtls_sha512_context *ctx, int is384 ); * \brief This function feeds an input buffer into an ongoing * SHA-512 checksum calculation. * - * \param ctx The SHA-512 context. - * \param input The buffer holding the input data. - * \param ilen The length of the input data. + * \param ctx The SHA-512 context. This must be initialized + * and have a hash operation started. + * \param input The buffer holding the input data. This must + * be a readable buffer of length \p ilen Bytes. + * \param ilen The length of the input data in Bytes. * * \return \c 0 on success. + * \return A negative error code on failure. */ int mbedtls_sha512_update_ret( mbedtls_sha512_context *ctx, const unsigned char *input, @@ -120,10 +130,13 @@ int mbedtls_sha512_update_ret( mbedtls_sha512_context *ctx, * the result to the output buffer. This function is for * internal use only. * - * \param ctx The SHA-512 context. + * \param ctx The SHA-512 context. This must be initialized + * and have a hash operation started. * \param output The SHA-384 or SHA-512 checksum result. + * This must be a writable buffer of length \c 64 Bytes. * * \return \c 0 on success. + * \return A negative error code on failure. */ int mbedtls_sha512_finish_ret( mbedtls_sha512_context *ctx, unsigned char output[64] ); @@ -132,10 +145,12 @@ int mbedtls_sha512_finish_ret( mbedtls_sha512_context *ctx, * \brief This function processes a single data block within * the ongoing SHA-512 computation. * - * \param ctx The SHA-512 context. - * \param data The buffer holding one block of data. + * \param ctx The SHA-512 context. This must be initialized. + * \param data The buffer holding one block of data. This + * must be a readable buffer of length \c 128 Bytes. * * \return \c 0 on success. + * \return A negative error code on failure. */ int mbedtls_internal_sha512_process( mbedtls_sha512_context *ctx, const unsigned char data[128] ); @@ -151,9 +166,9 @@ int mbedtls_internal_sha512_process( mbedtls_sha512_context *ctx, * * \deprecated Superseded by mbedtls_sha512_starts_ret() in 2.7.0 * - * \param ctx The SHA-512 context to initialize. - * \param is384 Determines which function to use: - * 0: Use SHA-512, or 1: Use SHA-384. + * \param ctx The SHA-512 context to use. This must be initialized. + * \param is384 Determines which function to use. This must be either + * \c 0 for SHA-512 or \c 1 for SHA-384. */ MBEDTLS_DEPRECATED void mbedtls_sha512_starts( mbedtls_sha512_context *ctx, int is384 ); @@ -164,9 +179,11 @@ MBEDTLS_DEPRECATED void mbedtls_sha512_starts( mbedtls_sha512_context *ctx, * * \deprecated Superseded by mbedtls_sha512_update_ret() in 2.7.0. * - * \param ctx The SHA-512 context. - * \param input The buffer holding the data. - * \param ilen The length of the input data. + * \param ctx The SHA-512 context. This must be initialized + * and have a hash operation started. + * \param input The buffer holding the data. This must be a readable + * buffer of length \p ilen Bytes. + * \param ilen The length of the input data in Bytes. */ MBEDTLS_DEPRECATED void mbedtls_sha512_update( mbedtls_sha512_context *ctx, const unsigned char *input, @@ -178,8 +195,10 @@ MBEDTLS_DEPRECATED void mbedtls_sha512_update( mbedtls_sha512_context *ctx, * * \deprecated Superseded by mbedtls_sha512_finish_ret() in 2.7.0. * - * \param ctx The SHA-512 context. - * \param output The SHA-384 or SHA-512 checksum result. + * \param ctx The SHA-512 context. This must be initialized + * and have a hash operation started. + * \param output The SHA-384 or SHA-512 checksum result. This must + * be a writable buffer of size \c 64 Bytes. */ MBEDTLS_DEPRECATED void mbedtls_sha512_finish( mbedtls_sha512_context *ctx, unsigned char output[64] ); @@ -191,8 +210,9 @@ MBEDTLS_DEPRECATED void mbedtls_sha512_finish( mbedtls_sha512_context *ctx, * * \deprecated Superseded by mbedtls_internal_sha512_process() in 2.7.0. * - * \param ctx The SHA-512 context. - * \param data The buffer holding one block of data. + * \param ctx The SHA-512 context. This must be initialized. + * \param data The buffer holding one block of data. This must be + * a readable buffer of length \c 128 Bytes. */ MBEDTLS_DEPRECATED void mbedtls_sha512_process( mbedtls_sha512_context *ctx, @@ -211,13 +231,16 @@ MBEDTLS_DEPRECATED void mbedtls_sha512_process( * The SHA-512 result is calculated as * output = SHA-512(input buffer). * - * \param input The buffer holding the input data. - * \param ilen The length of the input data. + * \param input The buffer holding the input data. This must be + * a readable buffer of length \p ilen Bytes. + * \param ilen The length of the input data in Bytes. * \param output The SHA-384 or SHA-512 checksum result. - * \param is384 Determines which function to use: - * 0: Use SHA-512, or 1: Use SHA-384. + * This must be a writable buffer of length \c 64 Bytes. + * \param is384 Determines which function to use. This must be either + * \c 0 for SHA-512, or \c 1 for SHA-384. * * \return \c 0 on success. + * \return A negative error code on failure. */ int mbedtls_sha512_ret( const unsigned char *input, size_t ilen, @@ -242,11 +265,13 @@ int mbedtls_sha512_ret( const unsigned char *input, * * \deprecated Superseded by mbedtls_sha512_ret() in 2.7.0 * - * \param input The buffer holding the data. - * \param ilen The length of the input data. - * \param output The SHA-384 or SHA-512 checksum result. - * \param is384 Determines which function to use: - * 0: Use SHA-512, or 1: Use SHA-384. + * \param input The buffer holding the data. This must be a + * readable buffer of length \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + * \param output The SHA-384 or SHA-512 checksum result. This must + * be a writable buffer of length \c 64 Bytes. + * \param is384 Determines which function to use. This must be either + * \c 0 for SHA-512, or \c 1 for SHA-384. */ MBEDTLS_DEPRECATED void mbedtls_sha512( const unsigned char *input, size_t ilen, diff --git a/thirdparty/mbedtls/include/mbedtls/ssl.h b/thirdparty/mbedtls/include/mbedtls/ssl.h index 2d511a8ea1..8106bb4ab0 100644 --- a/thirdparty/mbedtls/include/mbedtls/ssl.h +++ b/thirdparty/mbedtls/include/mbedtls/ssl.h @@ -121,6 +121,8 @@ #define MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH -0x6600 /**< Couldn't set the hash for verifying CertificateVerify */ #define MBEDTLS_ERR_SSL_CONTINUE_PROCESSING -0x6580 /**< Internal-only message signaling that further message-processing should be done */ #define MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS -0x6500 /**< The asynchronous operation is not completed yet. */ +#define MBEDTLS_ERR_SSL_EARLY_MESSAGE -0x6480 /**< Internal-only message signaling that a message arrived early. */ +#define MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS -0x7000 /**< A cryptographic operation is in progress. Try again later. */ /* * Various constants @@ -242,6 +244,14 @@ #define MBEDTLS_SSL_OUT_CONTENT_LEN MBEDTLS_SSL_MAX_CONTENT_LEN #endif +/* + * Maximum number of heap-allocated bytes for the purpose of + * DTLS handshake message reassembly and future message buffering. + */ +#if !defined(MBEDTLS_SSL_DTLS_MAX_BUFFERING) +#define MBEDTLS_SSL_DTLS_MAX_BUFFERING 32768 +#endif + /* \} name SECTION: Module settings */ /* @@ -1022,14 +1032,14 @@ struct mbedtls_ssl_context int renego_records_seen; /*!< Records since renego request, or with DTLS, number of retransmissions of request if renego_max_records is < 0 */ -#endif +#endif /* MBEDTLS_SSL_RENEGOTIATION */ int major_ver; /*!< equal to MBEDTLS_SSL_MAJOR_VERSION_3 */ int minor_ver; /*!< either 0 (SSL3) or 1 (TLS1.0) */ #if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) unsigned badmac_seen; /*!< records with a bad MAC received */ -#endif +#endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT */ mbedtls_ssl_send_t *f_send; /*!< Callback for network send */ mbedtls_ssl_recv_t *f_recv; /*!< Callback for network receive */ @@ -1085,11 +1095,11 @@ struct mbedtls_ssl_context uint16_t in_epoch; /*!< DTLS epoch for incoming records */ size_t next_record_offset; /*!< offset of the next record in datagram (equal to in_left if none) */ -#endif +#endif /* MBEDTLS_SSL_PROTO_DTLS */ #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) uint64_t in_window_top; /*!< last validated record seq_num */ uint64_t in_window; /*!< bitmask for replay detection */ -#endif +#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ size_t in_hslen; /*!< current handshake message length, including the handshake header */ @@ -1098,6 +1108,11 @@ struct mbedtls_ssl_context int keep_current_message; /*!< drop or reuse current message on next call to record layer? */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + uint8_t disable_datagram_packing; /*!< Disable packing multiple records + * within a single datagram. */ +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + /* * Record layer (outgoing data) */ @@ -1112,12 +1127,18 @@ struct mbedtls_ssl_context size_t out_msglen; /*!< record header: message length */ size_t out_left; /*!< amount of data not yet written */ + unsigned char cur_out_ctr[8]; /*!< Outgoing record sequence number. */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + uint16_t mtu; /*!< path mtu, used to fragment outgoing messages */ +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + #if defined(MBEDTLS_ZLIB_SUPPORT) unsigned char *compress_buf; /*!< zlib data buffer */ -#endif +#endif /* MBEDTLS_ZLIB_SUPPORT */ #if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) signed char split_done; /*!< current record already splitted? */ -#endif +#endif /* MBEDTLS_SSL_CBC_RECORD_SPLITTING */ /* * PKI layer @@ -1130,11 +1151,11 @@ struct mbedtls_ssl_context #if defined(MBEDTLS_X509_CRT_PARSE_C) char *hostname; /*!< expected peer CN for verification (and SNI if available) */ -#endif +#endif /* MBEDTLS_X509_CRT_PARSE_C */ #if defined(MBEDTLS_SSL_ALPN) const char *alpn_chosen; /*!< negotiated protocol */ -#endif +#endif /* MBEDTLS_SSL_ALPN */ /* * Information for DTLS hello verify @@ -1142,7 +1163,7 @@ struct mbedtls_ssl_context #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) unsigned char *cli_id; /*!< transport-level ID of the client */ size_t cli_id_len; /*!< length of cli_id */ -#endif +#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY && MBEDTLS_SSL_SRV_C */ /* * Secure renegotiation @@ -1154,7 +1175,7 @@ struct mbedtls_ssl_context size_t verify_data_len; /*!< length of verify data stored */ char own_verify_data[MBEDTLS_SSL_VERIFY_DATA_MAX_LEN]; /*!< previous handshake verify data */ char peer_verify_data[MBEDTLS_SSL_VERIFY_DATA_MAX_LEN]; /*!< previous handshake verify data */ -#endif +#endif /* MBEDTLS_SSL_RENEGOTIATION */ }; #if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) @@ -1374,6 +1395,52 @@ void mbedtls_ssl_set_bio( mbedtls_ssl_context *ssl, mbedtls_ssl_recv_t *f_recv, mbedtls_ssl_recv_timeout_t *f_recv_timeout ); +#if defined(MBEDTLS_SSL_PROTO_DTLS) +/** + * \brief Set the Maximum Tranport Unit (MTU). + * Special value: 0 means unset (no limit). + * This represents the maximum size of a datagram payload + * handled by the transport layer (usually UDP) as determined + * by the network link and stack. In practice, this controls + * the maximum size datagram the DTLS layer will pass to the + * \c f_send() callback set using \c mbedtls_ssl_set_bio(). + * + * \note The limit on datagram size is converted to a limit on + * record payload by subtracting the current overhead of + * encapsulation and encryption/authentication if any. + * + * \note This can be called at any point during the connection, for + * example when a Path Maximum Transfer Unit (PMTU) + * estimate becomes available from other sources, + * such as lower (or higher) protocol layers. + * + * \note This setting only controls the size of the packets we send, + * and does not restrict the size of the datagrams we're + * willing to receive. Client-side, you can request the + * server to use smaller records with \c + * mbedtls_ssl_conf_max_frag_len(). + * + * \note If both a MTU and a maximum fragment length have been + * configured (or negotiated with the peer), the resulting + * lower limit on record payload (see first note) is used. + * + * \note This can only be used to decrease the maximum size + * of datagrams (hence records, see first note) sent. It + * cannot be used to increase the maximum size of records over + * the limit set by #MBEDTLS_SSL_OUT_CONTENT_LEN. + * + * \note Values lower than the current record layer expansion will + * result in an error when trying to send data. + * + * \note Using record compression together with a non-zero MTU value + * will result in an error when trying to send data. + * + * \param ssl SSL context + * \param mtu Value of the path MTU in bytes + */ +void mbedtls_ssl_set_mtu( mbedtls_ssl_context *ssl, uint16_t mtu ); +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + /** * \brief Set the timeout period for mbedtls_ssl_read() * (Default: no timeout.) @@ -1757,6 +1824,38 @@ void mbedtls_ssl_conf_dtls_badmac_limit( mbedtls_ssl_config *conf, unsigned limi #endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT */ #if defined(MBEDTLS_SSL_PROTO_DTLS) + +/** + * \brief Allow or disallow packing of multiple handshake records + * within a single datagram. + * + * \param ssl The SSL context to configure. + * \param allow_packing This determines whether datagram packing may + * be used or not. A value of \c 0 means that every + * record will be sent in a separate datagram; a + * value of \c 1 means that, if space permits, + * multiple handshake messages (including CCS) belonging to + * a single flight may be packed within a single datagram. + * + * \note This is enabled by default and should only be disabled + * for test purposes, or if datagram packing causes + * interoperability issues with peers that don't support it. + * + * \note Allowing datagram packing reduces the network load since + * there's less overhead if multiple messages share the same + * datagram. Also, it increases the handshake efficiency + * since messages belonging to a single datagram will not + * be reordered in transit, and so future message buffering + * or flight retransmission (if no buffering is used) as + * means to deal with reordering are needed less frequently. + * + * \note Application records are not affected by this option and + * are currently always sent in separate datagrams. + * + */ +void mbedtls_ssl_set_datagram_packing( mbedtls_ssl_context *ssl, + unsigned allow_packing ); + /** * \brief Set retransmit timeout values for the DTLS handshake. * (DTLS only, no effect on TLS.) @@ -1945,6 +2044,14 @@ void mbedtls_ssl_conf_ca_chain( mbedtls_ssl_config *conf, * whether it matches those preferences - the server can then * decide what it wants to do with it. * + * \note The provided \p pk_key needs to match the public key in the + * first certificate in \p own_cert, or all handshakes using + * that certificate will fail. It is your responsibility + * to ensure that; this function will not perform any check. + * You may use mbedtls_pk_check_pair() in order to perform + * this check yourself, but be aware that this function can + * be computationally expensive on some key types. + * * \param conf SSL configuration * \param own_cert own public certificate chain * \param pk_key own private key @@ -2433,6 +2540,18 @@ void mbedtls_ssl_conf_cert_req_ca_list( mbedtls_ssl_config *conf, * (Client: set maximum fragment length to emit *and* * negotiate with the server during handshake) * + * \note With TLS, this currently only affects ApplicationData (sent + * with \c mbedtls_ssl_read()), not handshake messages. + * With DTLS, this affects both ApplicationData and handshake. + * + * \note This sets the maximum length for a record's payload, + * excluding record overhead that will be added to it, see + * \c mbedtls_ssl_get_record_expansion(). + * + * \note For DTLS, it is also possible to set a limit for the total + * size of daragrams passed to the transport layer, including + * record overhead, see \c mbedtls_ssl_set_mtu(). + * * \param conf SSL configuration * \param mfl_code Code for maximum fragment length (allowed values: * MBEDTLS_SSL_MAX_FRAG_LEN_512, MBEDTLS_SSL_MAX_FRAG_LEN_1024, @@ -2663,13 +2782,14 @@ size_t mbedtls_ssl_get_bytes_avail( const mbedtls_ssl_context *ssl ); /** * \brief Return the result of the certificate verification * - * \param ssl SSL context + * \param ssl The SSL context to use. * - * \return 0 if successful, - * -1 if result is not available (eg because the handshake was - * aborted too early), or - * a combination of BADCERT_xxx and BADCRL_xxx flags, see - * x509.h + * \return \c 0 if the certificate verification was successful. + * \return \c -1u if the result is not available. This may happen + * e.g. if the handshake aborts early, or a verification + * callback returned a fatal error. + * \return A bitwise combination of \c MBEDTLS_X509_BADCERT_XXX + * and \c MBEDTLS_X509_BADCRL_XXX failure flags; see x509.h. */ uint32_t mbedtls_ssl_get_verify_result( const mbedtls_ssl_context *ssl ); @@ -2695,6 +2815,9 @@ const char *mbedtls_ssl_get_version( const mbedtls_ssl_context *ssl ); * \brief Return the (maximum) number of bytes added by the record * layer: header + encryption/MAC overhead (inc. padding) * + * \note This function is not available (always returns an error) + * when record compression is enabled. + * * \param ssl SSL context * * \return Current maximum record expansion in bytes, or @@ -2709,6 +2832,23 @@ int mbedtls_ssl_get_record_expansion( const mbedtls_ssl_context *ssl ); * This is the value negotiated with peer if any, * or the locally configured value. * + * \sa mbedtls_ssl_conf_max_frag_len() + * \sa mbedtls_ssl_get_max_record_payload() + * + * \param ssl SSL context + * + * \return Current maximum fragment length. + */ +size_t mbedtls_ssl_get_max_frag_len( const mbedtls_ssl_context *ssl ); +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +/** + * \brief Return the current maximum outgoing record payload in bytes. + * This takes into account the config.h setting \c + * MBEDTLS_SSL_OUT_CONTENT_LEN, the configured and negotiated + * max fragment length extension if used, and for DTLS the + * path MTU as configured and current record expansion. + * * \note With DTLS, \c mbedtls_ssl_write() will return an error if * called with a larger length value. * With TLS, \c mbedtls_ssl_write() will fragment the input if @@ -2716,12 +2856,19 @@ int mbedtls_ssl_get_record_expansion( const mbedtls_ssl_context *ssl ); * to the caller to call \c mbedtls_ssl_write() again in * order to send the remaining bytes if any. * + * \note This function is not available (always returns an error) + * when record compression is enabled. + * + * \sa mbedtls_ssl_set_mtu() + * \sa mbedtls_ssl_get_max_frag_len() + * \sa mbedtls_ssl_get_record_expansion() + * * \param ssl SSL context * - * \return Current maximum fragment length. + * \return Current maximum payload for an outgoing record, + * or a negative error code. */ -size_t mbedtls_ssl_get_max_frag_len( const mbedtls_ssl_context *ssl ); -#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ +int mbedtls_ssl_get_max_out_record_payload( const mbedtls_ssl_context *ssl ); #if defined(MBEDTLS_X509_CRT_PARSE_C) /** @@ -2776,35 +2923,50 @@ int mbedtls_ssl_get_session( const mbedtls_ssl_context *ssl, mbedtls_ssl_session * * \param ssl SSL context * - * \return 0 if successful, or - * MBEDTLS_ERR_SSL_WANT_READ or MBEDTLS_ERR_SSL_WANT_WRITE, or - * MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED (see below), or - * a specific SSL error code. + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_SSL_WANT_READ or #MBEDTLS_ERR_SSL_WANT_WRITE + * if the handshake is incomplete and waiting for data to + * be available for reading from or writing to the underlying + * transport - in this case you must call this function again + * when the underlying transport is ready for the operation. + * \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if an asynchronous + * operation is in progress (see + * mbedtls_ssl_conf_async_private_cb()) - in this case you + * must call this function again when the operation is ready. + * \return #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS if a cryptographic + * operation is in progress (see mbedtls_ecp_set_max_ops()) - + * in this case you must call this function again to complete + * the handshake when you're done attending other tasks. + * \return #MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED if DTLS is in use + * and the client did not demonstrate reachability yet - in + * this case you must stop using the context (see below). + * \return Another SSL error code - in this case you must stop using + * the context (see below). + * + * \warning If this function returns something other than + * \c 0, + * #MBEDTLS_ERR_SSL_WANT_READ, + * #MBEDTLS_ERR_SSL_WANT_WRITE, + * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS or + * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS, + * you must stop using the SSL context for reading or writing, + * and either free it or call \c mbedtls_ssl_session_reset() + * on it before re-using it for a new connection; the current + * connection must be closed. * - * If this function returns MBEDTLS_ERR_SSL_WANT_READ, the - * handshake is unfinished and no further data is available - * from the underlying transport. In this case, you must call - * the function again at some later stage. + * \note If DTLS is in use, then you may choose to handle + * #MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED specially for logging + * purposes, as it is an expected return value rather than an + * actual error, but you still need to reset/free the context. * * \note Remarks regarding event-driven DTLS: - * If the function returns MBEDTLS_ERR_SSL_WANT_READ, no datagram + * If the function returns #MBEDTLS_ERR_SSL_WANT_READ, no datagram * from the underlying transport layer is currently being processed, * and it is safe to idle until the timer or the underlying transport * signal a new event. This is not true for a successful handshake, * in which case the datagram of the underlying transport that is * currently being processed might or might not contain further * DTLS records. - * - * \note If this function returns something other than 0 or - * MBEDTLS_ERR_SSL_WANT_READ/WRITE, you must stop using - * the SSL context for reading or writing, and either free it or - * call \c mbedtls_ssl_session_reset() on it before re-using it - * for a new connection; the current connection must be closed. - * - * \note If DTLS is in use, then you may choose to handle - * MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED specially for logging - * purposes, as it is an expected return value rather than an - * actual error, but you still need to reset/free the context. */ int mbedtls_ssl_handshake( mbedtls_ssl_context *ssl ); @@ -2812,20 +2974,21 @@ int mbedtls_ssl_handshake( mbedtls_ssl_context *ssl ); * \brief Perform a single step of the SSL handshake * * \note The state of the context (ssl->state) will be at - * the next state after execution of this function. Do not + * the next state after this function returns \c 0. Do not * call this function if state is MBEDTLS_SSL_HANDSHAKE_OVER. * - * \note If this function returns something other than 0 or - * MBEDTLS_ERR_SSL_WANT_READ/WRITE, you must stop using - * the SSL context for reading or writing, and either free it or - * call \c mbedtls_ssl_session_reset() on it before re-using it - * for a new connection; the current connection must be closed. - * * \param ssl SSL context * - * \return 0 if successful, or - * MBEDTLS_ERR_SSL_WANT_READ or MBEDTLS_ERR_SSL_WANT_WRITE, or - * a specific SSL error code. + * \return See mbedtls_ssl_handshake(). + * + * \warning If this function returns something other than \c 0, + * #MBEDTLS_ERR_SSL_WANT_READ, #MBEDTLS_ERR_SSL_WANT_WRITE, + * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS or + * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS, you must stop using + * the SSL context for reading or writing, and either free it + * or call \c mbedtls_ssl_session_reset() on it before + * re-using it for a new connection; the current connection + * must be closed. */ int mbedtls_ssl_handshake_step( mbedtls_ssl_context *ssl ); @@ -2840,13 +3003,18 @@ int mbedtls_ssl_handshake_step( mbedtls_ssl_context *ssl ); * \param ssl SSL context * * \return 0 if successful, or any mbedtls_ssl_handshake() return - * value. + * value except #MBEDTLS_ERR_SSL_CLIENT_RECONNECT that can't + * happen during a renegotiation. + * + * \warning If this function returns something other than \c 0, + * #MBEDTLS_ERR_SSL_WANT_READ, #MBEDTLS_ERR_SSL_WANT_WRITE, + * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS or + * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS, you must stop using + * the SSL context for reading or writing, and either free it + * or call \c mbedtls_ssl_session_reset() on it before + * re-using it for a new connection; the current connection + * must be closed. * - * \note If this function returns something other than 0 or - * MBEDTLS_ERR_SSL_WANT_READ/WRITE, you must stop using - * the SSL context for reading or writing, and either free it or - * call \c mbedtls_ssl_session_reset() on it before re-using it - * for a new connection; the current connection must be closed. */ int mbedtls_ssl_renegotiate( mbedtls_ssl_context *ssl ); #endif /* MBEDTLS_SSL_RENEGOTIATION */ @@ -2858,42 +3026,56 @@ int mbedtls_ssl_renegotiate( mbedtls_ssl_context *ssl ); * \param buf buffer that will hold the data * \param len maximum number of bytes to read * - * \return One of the following: - * - 0 if the read end of the underlying transport was closed, - * - the (positive) number of bytes read, or - * - a negative error code on failure. - * - * If MBEDTLS_ERR_SSL_WANT_READ is returned, no application data - * is available from the underlying transport. In this case, - * the function needs to be called again at some later stage. - * - * If MBEDTLS_ERR_SSL_WANT_WRITE is returned, a write is pending - * but the underlying transport isn't available for writing. In this - * case, the function needs to be called again at some later stage. + * \return The (positive) number of bytes read if successful. + * \return \c 0 if the read end of the underlying transport was closed + * - in this case you must stop using the context (see below). + * \return #MBEDTLS_ERR_SSL_WANT_READ or #MBEDTLS_ERR_SSL_WANT_WRITE + * if the handshake is incomplete and waiting for data to + * be available for reading from or writing to the underlying + * transport - in this case you must call this function again + * when the underlying transport is ready for the operation. + * \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if an asynchronous + * operation is in progress (see + * mbedtls_ssl_conf_async_private_cb()) - in this case you + * must call this function again when the operation is ready. + * \return #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS if a cryptographic + * operation is in progress (see mbedtls_ecp_set_max_ops()) - + * in this case you must call this function again to complete + * the handshake when you're done attending other tasks. + * \return #MBEDTLS_ERR_SSL_CLIENT_RECONNECT if we're at the server + * side of a DTLS connection and the client is initiating a + * new connection using the same source port. See below. + * \return Another SSL error code - in this case you must stop using + * the context (see below). + * + * \warning If this function returns something other than + * a positive value, + * #MBEDTLS_ERR_SSL_WANT_READ, + * #MBEDTLS_ERR_SSL_WANT_WRITE, + * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS, + * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS or + * #MBEDTLS_ERR_SSL_CLIENT_RECONNECT, + * you must stop using the SSL context for reading or writing, + * and either free it or call \c mbedtls_ssl_session_reset() + * on it before re-using it for a new connection; the current + * connection must be closed. * - * When this function return MBEDTLS_ERR_SSL_CLIENT_RECONNECT + * \note When this function returns #MBEDTLS_ERR_SSL_CLIENT_RECONNECT * (which can only happen server-side), it means that a client * is initiating a new connection using the same source port. * You can either treat that as a connection close and wait * for the client to resend a ClientHello, or directly * continue with \c mbedtls_ssl_handshake() with the same - * context (as it has beeen reset internally). Either way, you - * should make sure this is seen by the application as a new + * context (as it has been reset internally). Either way, you + * must make sure this is seen by the application as a new * connection: application state, if any, should be reset, and * most importantly the identity of the client must be checked * again. WARNING: not validating the identity of the client * again, or not transmitting the new identity to the * application layer, would allow authentication bypass! * - * \note If this function returns something other than a positive value - * or MBEDTLS_ERR_SSL_WANT_READ/WRITE or MBEDTLS_ERR_SSL_CLIENT_RECONNECT, - * you must stop using the SSL context for reading or writing, - * and either free it or call \c mbedtls_ssl_session_reset() on it - * before re-using it for a new connection; the current connection - * must be closed. - * * \note Remarks regarding event-driven DTLS: - * - If the function returns MBEDTLS_ERR_SSL_WANT_READ, no datagram + * - If the function returns #MBEDTLS_ERR_SSL_WANT_READ, no datagram * from the underlying transport layer is currently being processed, * and it is safe to idle until the timer or the underlying transport * signal a new event. @@ -2922,21 +3104,39 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ) * \param buf buffer holding the data * \param len how many bytes must be written * - * \return the number of bytes actually written (may be less than len), - * or MBEDTLS_ERR_SSL_WANT_WRITE or MBEDTLS_ERR_SSL_WANT_READ, - * or another negative error code. - * - * \note If this function returns something other than 0, a positive - * value or MBEDTLS_ERR_SSL_WANT_READ/WRITE, you must stop - * using the SSL context for reading or writing, and either - * free it or call \c mbedtls_ssl_session_reset() on it before - * re-using it for a new connection; the current connection - * must be closed. + * \return The (non-negative) number of bytes actually written if + * successful (may be less than \p len). + * \return #MBEDTLS_ERR_SSL_WANT_READ or #MBEDTLS_ERR_SSL_WANT_WRITE + * if the handshake is incomplete and waiting for data to + * be available for reading from or writing to the underlying + * transport - in this case you must call this function again + * when the underlying transport is ready for the operation. + * \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if an asynchronous + * operation is in progress (see + * mbedtls_ssl_conf_async_private_cb()) - in this case you + * must call this function again when the operation is ready. + * \return #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS if a cryptographic + * operation is in progress (see mbedtls_ecp_set_max_ops()) - + * in this case you must call this function again to complete + * the handshake when you're done attending other tasks. + * \return Another SSL error code - in this case you must stop using + * the context (see below). + * + * \warning If this function returns something other than + * a non-negative value, + * #MBEDTLS_ERR_SSL_WANT_READ, + * #MBEDTLS_ERR_SSL_WANT_WRITE, + * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS or + * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS, + * you must stop using the SSL context for reading or writing, + * and either free it or call \c mbedtls_ssl_session_reset() + * on it before re-using it for a new connection; the current + * connection must be closed. * - * \note When this function returns MBEDTLS_ERR_SSL_WANT_WRITE/READ, + * \note When this function returns #MBEDTLS_ERR_SSL_WANT_WRITE/READ, * it must be called later with the *same* arguments, * until it returns a value greater that or equal to 0. When - * the function returns MBEDTLS_ERR_SSL_WANT_WRITE there may be + * the function returns #MBEDTLS_ERR_SSL_WANT_WRITE there may be * some partial data in the output buffer, however this is not * yet sent. * diff --git a/thirdparty/mbedtls/include/mbedtls/ssl_cookie.h b/thirdparty/mbedtls/include/mbedtls/ssl_cookie.h index 80b65bbbb9..6a0ad4fa96 100644 --- a/thirdparty/mbedtls/include/mbedtls/ssl_cookie.h +++ b/thirdparty/mbedtls/include/mbedtls/ssl_cookie.h @@ -50,7 +50,7 @@ extern "C" { /** * \brief Context for the default cookie functions. */ -typedef struct +typedef struct mbedtls_ssl_cookie_ctx { mbedtls_md_context_t hmac_ctx; /*!< context for the HMAC portion */ #if !defined(MBEDTLS_HAVE_TIME) diff --git a/thirdparty/mbedtls/include/mbedtls/ssl_internal.h b/thirdparty/mbedtls/include/mbedtls/ssl_internal.h index d214703d77..97abb9f90b 100644 --- a/thirdparty/mbedtls/include/mbedtls/ssl_internal.h +++ b/thirdparty/mbedtls/include/mbedtls/ssl_internal.h @@ -93,6 +93,14 @@ #endif /* MBEDTLS_SSL_PROTO_TLS1_1 */ #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ +/* Shorthand for restartable ECC */ +#if defined(MBEDTLS_ECP_RESTARTABLE) && \ + defined(MBEDTLS_SSL_CLI_C) && \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +#define MBEDTLS_SSL__ECP_RESTARTABLE +#endif + #define MBEDTLS_SSL_INITIAL_HANDSHAKE 0 #define MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS 1 /* In progress */ #define MBEDTLS_SSL_RENEGOTIATION_DONE 2 /* Done or aborted */ @@ -155,6 +163,9 @@ #define MBEDTLS_SSL_OUT_PAYLOAD_LEN ( MBEDTLS_SSL_PAYLOAD_OVERHEAD + \ ( MBEDTLS_SSL_OUT_CONTENT_LEN ) ) +/* The maximum number of buffered handshake messages. */ +#define MBEDTLS_SSL_MAX_BUFFERED_HS 4 + /* Maximum length we can advertise as our max content length for RFC 6066 max_fragment_length extension negotiation purposes (the lesser of both sizes, if they are unequal.) @@ -284,7 +295,18 @@ struct mbedtls_ssl_handshake_params mbedtls_x509_crl *sni_ca_crl; /*!< trusted CAs CRLs from SNI */ #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ - +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + int ecrs_enabled; /*!< Handshake supports EC restart? */ + mbedtls_x509_crt_restart_ctx ecrs_ctx; /*!< restart context */ + enum { /* this complements ssl->state with info on intra-state operations */ + ssl_ecrs_none = 0, /*!< nothing going on (yet) */ + ssl_ecrs_crt_verify, /*!< Certificate: crt_verify() */ + ssl_ecrs_ske_start_processing, /*!< ServerKeyExchange: pk_verify() */ + ssl_ecrs_cke_ecdh_calc_secret, /*!< ClientKeyExchange: ECDH step 2 */ + ssl_ecrs_crt_vrfy_sign, /*!< CertificateVerify: pk_sign() */ + } ecrs_state; /*!< current (or last) operation */ + size_t ecrs_n; /*!< place for saving a length */ +#endif #if defined(MBEDTLS_SSL_PROTO_DTLS) unsigned int out_msg_seq; /*!< Outgoing handshake sequence number */ unsigned int in_msg_seq; /*!< Incoming handshake sequence number */ @@ -294,18 +316,45 @@ struct mbedtls_ssl_handshake_params unsigned char verify_cookie_len; /*!< Cli: cookie length Srv: flag for sending a cookie */ - unsigned char *hs_msg; /*!< Reassembled handshake message */ - uint32_t retransmit_timeout; /*!< Current value of timeout */ unsigned char retransmit_state; /*!< Retransmission state */ - mbedtls_ssl_flight_item *flight; /*!< Current outgoing flight */ - mbedtls_ssl_flight_item *cur_msg; /*!< Current message in flight */ + mbedtls_ssl_flight_item *flight; /*!< Current outgoing flight */ + mbedtls_ssl_flight_item *cur_msg; /*!< Current message in flight */ + unsigned char *cur_msg_p; /*!< Position in current message */ unsigned int in_flight_start_seq; /*!< Minimum message sequence in the flight being received */ mbedtls_ssl_transform *alt_transform_out; /*!< Alternative transform for resending messages */ unsigned char alt_out_ctr[8]; /*!< Alternative record epoch/counter for resending messages */ + + struct + { + size_t total_bytes_buffered; /*!< Cumulative size of heap allocated + * buffers used for message buffering. */ + + uint8_t seen_ccs; /*!< Indicates if a CCS message has + * been seen in the current flight. */ + + struct mbedtls_ssl_hs_buffer + { + unsigned is_valid : 1; + unsigned is_fragmented : 1; + unsigned is_complete : 1; + unsigned char *data; + size_t data_len; + } hs[MBEDTLS_SSL_MAX_BUFFERED_HS]; + + struct + { + unsigned char *data; + size_t len; + unsigned epoch; + } future_record; + + } buffering; + + uint16_t mtu; /*!< Handshake mtu, used to fragment outgoing messages */ #endif /* MBEDTLS_SSL_PROTO_DTLS */ /* @@ -364,6 +413,8 @@ struct mbedtls_ssl_handshake_params #endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ }; +typedef struct mbedtls_ssl_hs_buffer mbedtls_ssl_hs_buffer; + /* * This structure contains a full set of runtime transform parameters * either in negotiation or active. @@ -478,7 +529,6 @@ int mbedtls_ssl_send_fatal_handshake_failure( mbedtls_ssl_context *ssl ); void mbedtls_ssl_reset_checksum( mbedtls_ssl_context *ssl ); int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ); -int mbedtls_ssl_read_record_layer( mbedtls_ssl_context *ssl ); int mbedtls_ssl_handle_message_type( mbedtls_ssl_context *ssl ); int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl ); void mbedtls_ssl_update_handshake_status( mbedtls_ssl_context *ssl ); @@ -490,7 +540,10 @@ void mbedtls_ssl_update_handshake_status( mbedtls_ssl_context *ssl ); * of the logic of (D)TLS from the implementation * of the secure transport. * - * \param ssl SSL context to use + * \param ssl The SSL context to use. + * \param update_hs_digest This indicates if the handshake digest + * should be automatically updated in case + * a handshake message is found. * * \return 0 or non-zero error code. * @@ -556,10 +609,12 @@ void mbedtls_ssl_update_handshake_status( mbedtls_ssl_context *ssl ); * following the above definition. * */ -int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl, + unsigned update_hs_digest ); int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want ); -int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_write_handshake_msg( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl, uint8_t force_flush ); int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl ); int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ); @@ -668,6 +723,7 @@ static inline size_t mbedtls_ssl_hs_hdr_len( const mbedtls_ssl_context *ssl ) void mbedtls_ssl_send_flight_completed( mbedtls_ssl_context *ssl ); void mbedtls_ssl_recv_flight_completed( mbedtls_ssl_context *ssl ); int mbedtls_ssl_resend( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_flight_transmit( mbedtls_ssl_context *ssl ); #endif /* Visible for testing purposes only */ diff --git a/thirdparty/mbedtls/include/mbedtls/ssl_ticket.h b/thirdparty/mbedtls/include/mbedtls/ssl_ticket.h index 93ad46ac9c..b2686df09f 100644 --- a/thirdparty/mbedtls/include/mbedtls/ssl_ticket.h +++ b/thirdparty/mbedtls/include/mbedtls/ssl_ticket.h @@ -44,7 +44,7 @@ extern "C" { /** * \brief Information for session ticket protection */ -typedef struct +typedef struct mbedtls_ssl_ticket_key { unsigned char name[4]; /*!< random key identifier */ uint32_t generation_time; /*!< key generation timestamp (seconds) */ @@ -55,7 +55,7 @@ mbedtls_ssl_ticket_key; /** * \brief Context for session ticket handling functions */ -typedef struct +typedef struct mbedtls_ssl_ticket_context { mbedtls_ssl_ticket_key keys[2]; /*!< ticket protection keys */ unsigned char active; /*!< index of the currently active key */ diff --git a/thirdparty/mbedtls/include/mbedtls/threading.h b/thirdparty/mbedtls/include/mbedtls/threading.h index c25daa5cdf..92e6e6b987 100644 --- a/thirdparty/mbedtls/include/mbedtls/threading.h +++ b/thirdparty/mbedtls/include/mbedtls/threading.h @@ -36,13 +36,16 @@ extern "C" { #endif +/* MBEDTLS_ERR_THREADING_FEATURE_UNAVAILABLE is deprecated and should not be + * used. */ #define MBEDTLS_ERR_THREADING_FEATURE_UNAVAILABLE -0x001A /**< The selected feature is not available. */ + #define MBEDTLS_ERR_THREADING_BAD_INPUT_DATA -0x001C /**< Bad input parameters to function. */ #define MBEDTLS_ERR_THREADING_MUTEX_ERROR -0x001E /**< Locking / unlocking / free failed with error code. */ #if defined(MBEDTLS_THREADING_PTHREAD) #include <pthread.h> -typedef struct +typedef struct mbedtls_threading_mutex_t { pthread_mutex_t mutex; char is_valid; @@ -99,6 +102,17 @@ extern int (*mbedtls_mutex_unlock)( mbedtls_threading_mutex_t *mutex ); #if defined(MBEDTLS_FS_IO) extern mbedtls_threading_mutex_t mbedtls_threading_readdir_mutex; #endif + +#if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_PLATFORM_GMTIME_R_ALT) +/* This mutex may or may not be used in the default definition of + * mbedtls_platform_gmtime_r(), but in order to determine that, + * we need to check POSIX features, hence modify _POSIX_C_SOURCE. + * With the current approach, this declaration is orphaned, lacking + * an accompanying definition, in case mbedtls_platform_gmtime_r() + * doesn't need it, but that's not a problem. */ +extern mbedtls_threading_mutex_t mbedtls_threading_gmtime_mutex; +#endif /* MBEDTLS_HAVE_TIME_DATE && !MBEDTLS_PLATFORM_GMTIME_R_ALT */ + #endif /* MBEDTLS_THREADING_C */ #ifdef __cplusplus diff --git a/thirdparty/mbedtls/include/mbedtls/timing.h b/thirdparty/mbedtls/include/mbedtls/timing.h index bbcb90688a..a965fe0d35 100644 --- a/thirdparty/mbedtls/include/mbedtls/timing.h +++ b/thirdparty/mbedtls/include/mbedtls/timing.h @@ -51,7 +51,7 @@ struct mbedtls_timing_hr_time /** * \brief Context for mbedtls_timing_set/get_delay() */ -typedef struct +typedef struct mbedtls_timing_delay_context { struct mbedtls_timing_hr_time timer; uint32_t int_ms; diff --git a/thirdparty/mbedtls/include/mbedtls/version.h b/thirdparty/mbedtls/include/mbedtls/version.h index eaf25d908c..56e7398a2a 100644 --- a/thirdparty/mbedtls/include/mbedtls/version.h +++ b/thirdparty/mbedtls/include/mbedtls/version.h @@ -39,7 +39,7 @@ * Major, Minor, Patchlevel */ #define MBEDTLS_VERSION_MAJOR 2 -#define MBEDTLS_VERSION_MINOR 12 +#define MBEDTLS_VERSION_MINOR 16 #define MBEDTLS_VERSION_PATCH 0 /** @@ -47,9 +47,9 @@ * MMNNPP00 * Major version | Minor version | Patch version */ -#define MBEDTLS_VERSION_NUMBER 0x020C0000 -#define MBEDTLS_VERSION_STRING "2.12.0" -#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.12.0" +#define MBEDTLS_VERSION_NUMBER 0x02100000 +#define MBEDTLS_VERSION_STRING "2.16.0" +#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.16.0" #if defined(MBEDTLS_VERSION_C) diff --git a/thirdparty/mbedtls/include/mbedtls/x509_crt.h b/thirdparty/mbedtls/include/mbedtls/x509_crt.h index ac23cffe84..3dd5922486 100644 --- a/thirdparty/mbedtls/include/mbedtls/x509_crt.h +++ b/thirdparty/mbedtls/include/mbedtls/x509_crt.h @@ -105,7 +105,7 @@ mbedtls_x509_crt; * * All lists are bitfields, built by ORing flags from MBEDTLS_X509_ID_FLAG(). */ -typedef struct +typedef struct mbedtls_x509_crt_profile { uint32_t allowed_mds; /**< MDs for signatures */ uint32_t allowed_pks; /**< PK algs for signatures */ @@ -143,6 +143,63 @@ typedef struct mbedtls_x509write_cert } mbedtls_x509write_cert; +/** + * Item in a verification chain: cert and flags for it + */ +typedef struct { + mbedtls_x509_crt *crt; + uint32_t flags; +} mbedtls_x509_crt_verify_chain_item; + +/** + * Max size of verification chain: end-entity + intermediates + trusted root + */ +#define MBEDTLS_X509_MAX_VERIFY_CHAIN_SIZE ( MBEDTLS_X509_MAX_INTERMEDIATE_CA + 2 ) + +/** + * Verification chain as built by \c mbedtls_crt_verify_chain() + */ +typedef struct +{ + mbedtls_x509_crt_verify_chain_item items[MBEDTLS_X509_MAX_VERIFY_CHAIN_SIZE]; + unsigned len; +} mbedtls_x509_crt_verify_chain; + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + +/** + * \brief Context for resuming X.509 verify operations + */ +typedef struct +{ + /* for check_signature() */ + mbedtls_pk_restart_ctx pk; + + /* for find_parent_in() */ + mbedtls_x509_crt *parent; /* non-null iff parent_in in progress */ + mbedtls_x509_crt *fallback_parent; + int fallback_signature_is_good; + + /* for find_parent() */ + int parent_is_trusted; /* -1 if find_parent is not in progress */ + + /* for verify_chain() */ + enum { + x509_crt_rs_none, + x509_crt_rs_find_parent, + } in_progress; /* none if no operation is in progress */ + int self_cnt; + mbedtls_x509_crt_verify_chain ver_chain; + +} mbedtls_x509_crt_restart_ctx; + +#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + +/* Now we can declare functions that take a pointer to that */ +typedef void mbedtls_x509_crt_restart_ctx; + +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + #if defined(MBEDTLS_X509_CRT_PARSE_C) /** * Default security profile. Should provide a good balance between security @@ -175,19 +232,34 @@ int mbedtls_x509_crt_parse_der( mbedtls_x509_crt *chain, const unsigned char *bu size_t buflen ); /** - * \brief Parse one or more certificates and add them - * to the chained list. Parses permissively. If some - * certificates can be parsed, the result is the number - * of failed certificates it encountered. If none complete - * correctly, the first error is returned. + * \brief Parse one DER-encoded or one or more concatenated PEM-encoded + * certificates and add them to the chained list. * - * \param chain points to the start of the chain - * \param buf buffer holding the certificate data in PEM or DER format - * \param buflen size of the buffer - * (including the terminating null byte for PEM data) + * For CRTs in PEM encoding, the function parses permissively: + * if at least one certificate can be parsed, the function + * returns the number of certificates for which parsing failed + * (hence \c 0 if all certificates were parsed successfully). + * If no certificate could be parsed, the function returns + * the first (negative) error encountered during parsing. + * + * PEM encoded certificates may be interleaved by other data + * such as human readable descriptions of their content, as + * long as the certificates are enclosed in the PEM specific + * '-----{BEGIN/END} CERTIFICATE-----' delimiters. + * + * \param chain The chain to which to add the parsed certificates. + * \param buf The buffer holding the certificate data in PEM or DER format. + * For certificates in PEM encoding, this may be a concatenation + * of multiple certificates; for DER encoding, the buffer must + * comprise exactly one certificate. + * \param buflen The size of \p buf, including the terminating \c NULL byte + * in case of PEM encoded data. + * + * \return \c 0 if all certificates were parsed successfully. + * \return The (positive) number of certificates that couldn't + * be parsed if parsing was partly successful (see above). + * \return A negative X509 or PEM error code otherwise. * - * \return 0 if all certificates parsed successfully, a positive number - * if partly successful or a specific X509 or PEM error code */ int mbedtls_x509_crt_parse( mbedtls_x509_crt *chain, const unsigned char *buf, size_t buflen ); @@ -353,6 +425,37 @@ int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt, int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), void *p_vrfy ); +/** + * \brief Restartable version of \c mbedtls_crt_verify_with_profile() + * + * \note Performs the same job as \c mbedtls_crt_verify_with_profile() + * but can return early and restart according to the limit + * set with \c mbedtls_ecp_set_max_ops() to reduce blocking. + * + * \param crt a certificate (chain) to be verified + * \param trust_ca the list of trusted CAs + * \param ca_crl the list of CRLs for trusted CAs + * \param profile security profile for verification + * \param cn expected Common Name (can be set to + * NULL if the CN must not be verified) + * \param flags result of the verification + * \param f_vrfy verification function + * \param p_vrfy verification parameter + * \param rs_ctx restart context (NULL to disable restart) + * + * \return See \c mbedtls_crt_verify_with_profile(), or + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + */ +int mbedtls_x509_crt_verify_restartable( mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + const mbedtls_x509_crt_profile *profile, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy, + mbedtls_x509_crt_restart_ctx *rs_ctx ); + #if defined(MBEDTLS_X509_CHECK_KEY_USAGE) /** * \brief Check usage of certificate against keyUsage extension. @@ -424,6 +527,18 @@ void mbedtls_x509_crt_init( mbedtls_x509_crt *crt ); * \param crt Certificate chain to free */ void mbedtls_x509_crt_free( mbedtls_x509_crt *crt ); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +/** + * \brief Initialize a restart context + */ +void mbedtls_x509_crt_restart_init( mbedtls_x509_crt_restart_ctx *ctx ); + +/** + * \brief Free the components of a restart context + */ +void mbedtls_x509_crt_restart_free( mbedtls_x509_crt_restart_ctx *ctx ); +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ /* \} name */ diff --git a/thirdparty/mbedtls/include/mbedtls/xtea.h b/thirdparty/mbedtls/include/mbedtls/xtea.h index 8df708a3a5..6430c1318a 100644 --- a/thirdparty/mbedtls/include/mbedtls/xtea.h +++ b/thirdparty/mbedtls/include/mbedtls/xtea.h @@ -37,6 +37,8 @@ #define MBEDTLS_XTEA_DECRYPT 0 #define MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH -0x0028 /**< The data input has an invalid length. */ + +/* MBEDTLS_ERR_XTEA_HW_ACCEL_FAILED is deprecated and should not be used. */ #define MBEDTLS_ERR_XTEA_HW_ACCEL_FAILED -0x0029 /**< XTEA hardware accelerator failed. */ #ifdef __cplusplus @@ -50,7 +52,7 @@ extern "C" { /** * \brief XTEA context structure */ -typedef struct +typedef struct mbedtls_xtea_context { uint32_t k[4]; /*!< key */ } diff --git a/thirdparty/mbedtls/library/aes.c b/thirdparty/mbedtls/library/aes.c index 5c939bba47..0543cd7817 100644 --- a/thirdparty/mbedtls/library/aes.c +++ b/thirdparty/mbedtls/library/aes.c @@ -36,6 +36,7 @@ #include <string.h> #include "mbedtls/aes.h" +#include "mbedtls/platform.h" #include "mbedtls/platform_util.h" #if defined(MBEDTLS_PADLOCK_C) #include "mbedtls/padlock.h" @@ -55,6 +56,12 @@ #if !defined(MBEDTLS_AES_ALT) +/* Parameter validation macros based on platform_util.h */ +#define AES_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_AES_BAD_INPUT_DATA ) +#define AES_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + /* * 32-bit integer manipulation macros (little endian) */ @@ -510,6 +517,8 @@ static void aes_gen_tables( void ) void mbedtls_aes_init( mbedtls_aes_context *ctx ) { + AES_VALIDATE( ctx != NULL ); + memset( ctx, 0, sizeof( mbedtls_aes_context ) ); } @@ -524,12 +533,17 @@ void mbedtls_aes_free( mbedtls_aes_context *ctx ) #if defined(MBEDTLS_CIPHER_MODE_XTS) void mbedtls_aes_xts_init( mbedtls_aes_xts_context *ctx ) { + AES_VALIDATE( ctx != NULL ); + mbedtls_aes_init( &ctx->crypt ); mbedtls_aes_init( &ctx->tweak ); } void mbedtls_aes_xts_free( mbedtls_aes_xts_context *ctx ) { + if( ctx == NULL ) + return; + mbedtls_aes_free( &ctx->crypt ); mbedtls_aes_free( &ctx->tweak ); } @@ -545,14 +559,8 @@ int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key, unsigned int i; uint32_t *RK; -#if !defined(MBEDTLS_AES_ROM_TABLES) - if( aes_init_done == 0 ) - { - aes_gen_tables(); - aes_init_done = 1; - - } -#endif + AES_VALIDATE_RET( ctx != NULL ); + AES_VALIDATE_RET( key != NULL ); switch( keybits ) { @@ -562,6 +570,14 @@ int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key, default : return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH ); } +#if !defined(MBEDTLS_AES_ROM_TABLES) + if( aes_init_done == 0 ) + { + aes_gen_tables(); + aes_init_done = 1; + } +#endif + #if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_PADLOCK_ALIGN16) if( aes_padlock_ace == -1 ) aes_padlock_ace = mbedtls_padlock_has_support( MBEDTLS_PADLOCK_ACE ); @@ -661,6 +677,9 @@ int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key, uint32_t *RK; uint32_t *SK; + AES_VALIDATE_RET( ctx != NULL ); + AES_VALIDATE_RET( key != NULL ); + mbedtls_aes_init( &cty ); #if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_PADLOCK_ALIGN16) @@ -751,6 +770,9 @@ int mbedtls_aes_xts_setkey_enc( mbedtls_aes_xts_context *ctx, const unsigned char *key1, *key2; unsigned int key1bits, key2bits; + AES_VALIDATE_RET( ctx != NULL ); + AES_VALIDATE_RET( key != NULL ); + ret = mbedtls_aes_xts_decode_keys( key, keybits, &key1, &key1bits, &key2, &key2bits ); if( ret != 0 ) @@ -773,6 +795,9 @@ int mbedtls_aes_xts_setkey_dec( mbedtls_aes_xts_context *ctx, const unsigned char *key1, *key2; unsigned int key1bits, key2bits; + AES_VALIDATE_RET( ctx != NULL ); + AES_VALIDATE_RET( key != NULL ); + ret = mbedtls_aes_xts_decode_keys( key, keybits, &key1, &key1bits, &key2, &key2bits ); if( ret != 0 ) @@ -976,10 +1001,16 @@ void mbedtls_aes_decrypt( mbedtls_aes_context *ctx, * AES-ECB block encryption/decryption */ int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx, - int mode, - const unsigned char input[16], - unsigned char output[16] ) + int mode, + const unsigned char input[16], + unsigned char output[16] ) { + AES_VALIDATE_RET( ctx != NULL ); + AES_VALIDATE_RET( input != NULL ); + AES_VALIDATE_RET( output != NULL ); + AES_VALIDATE_RET( mode == MBEDTLS_AES_ENCRYPT || + mode == MBEDTLS_AES_DECRYPT ); + #if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) if( mbedtls_aesni_has_support( MBEDTLS_AESNI_AES ) ) return( mbedtls_aesni_crypt_ecb( ctx, mode, input, output ) ); @@ -1017,6 +1048,13 @@ int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx, int i; unsigned char temp[16]; + AES_VALIDATE_RET( ctx != NULL ); + AES_VALIDATE_RET( mode == MBEDTLS_AES_ENCRYPT || + mode == MBEDTLS_AES_DECRYPT ); + AES_VALIDATE_RET( iv != NULL ); + AES_VALIDATE_RET( input != NULL ); + AES_VALIDATE_RET( output != NULL ); + if( length % 16 ) return( MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH ); @@ -1142,11 +1180,18 @@ int mbedtls_aes_crypt_xts( mbedtls_aes_xts_context *ctx, unsigned char prev_tweak[16]; unsigned char tmp[16]; - /* Sectors must be at least 16 bytes. */ + AES_VALIDATE_RET( ctx != NULL ); + AES_VALIDATE_RET( mode == MBEDTLS_AES_ENCRYPT || + mode == MBEDTLS_AES_DECRYPT ); + AES_VALIDATE_RET( data_unit != NULL ); + AES_VALIDATE_RET( input != NULL ); + AES_VALIDATE_RET( output != NULL ); + + /* Data units must be at least 16 bytes long. */ if( length < 16 ) return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH; - /* NIST SP 80-38E disallows data units larger than 2**20 blocks. */ + /* NIST SP 800-38E disallows data units larger than 2**20 blocks. */ if( length > ( 1 << 20 ) * 16 ) return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH; @@ -1241,7 +1286,20 @@ int mbedtls_aes_crypt_cfb128( mbedtls_aes_context *ctx, unsigned char *output ) { int c; - size_t n = *iv_off; + size_t n; + + AES_VALIDATE_RET( ctx != NULL ); + AES_VALIDATE_RET( mode == MBEDTLS_AES_ENCRYPT || + mode == MBEDTLS_AES_DECRYPT ); + AES_VALIDATE_RET( iv_off != NULL ); + AES_VALIDATE_RET( iv != NULL ); + AES_VALIDATE_RET( input != NULL ); + AES_VALIDATE_RET( output != NULL ); + + n = *iv_off; + + if( n > 15 ) + return( MBEDTLS_ERR_AES_BAD_INPUT_DATA ); if( mode == MBEDTLS_AES_DECRYPT ) { @@ -1279,15 +1337,21 @@ int mbedtls_aes_crypt_cfb128( mbedtls_aes_context *ctx, * AES-CFB8 buffer encryption/decryption */ int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx, - int mode, - size_t length, - unsigned char iv[16], - const unsigned char *input, - unsigned char *output ) + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) { unsigned char c; unsigned char ov[17]; + AES_VALIDATE_RET( ctx != NULL ); + AES_VALIDATE_RET( mode == MBEDTLS_AES_ENCRYPT || + mode == MBEDTLS_AES_DECRYPT ); + AES_VALIDATE_RET( iv != NULL ); + AES_VALIDATE_RET( input != NULL ); + AES_VALIDATE_RET( output != NULL ); while( length-- ) { memcpy( ov, iv, 16 ); @@ -1320,7 +1384,18 @@ int mbedtls_aes_crypt_ofb( mbedtls_aes_context *ctx, unsigned char *output ) { int ret = 0; - size_t n = *iv_off; + size_t n; + + AES_VALIDATE_RET( ctx != NULL ); + AES_VALIDATE_RET( iv_off != NULL ); + AES_VALIDATE_RET( iv != NULL ); + AES_VALIDATE_RET( input != NULL ); + AES_VALIDATE_RET( output != NULL ); + + n = *iv_off; + + if( n > 15 ) + return( MBEDTLS_ERR_AES_BAD_INPUT_DATA ); while( length-- ) { @@ -1355,7 +1430,16 @@ int mbedtls_aes_crypt_ctr( mbedtls_aes_context *ctx, unsigned char *output ) { int c, i; - size_t n = *nc_off; + size_t n; + + AES_VALIDATE_RET( ctx != NULL ); + AES_VALIDATE_RET( nc_off != NULL ); + AES_VALIDATE_RET( nonce_counter != NULL ); + AES_VALIDATE_RET( stream_block != NULL ); + AES_VALIDATE_RET( input != NULL ); + AES_VALIDATE_RET( output != NULL ); + + n = *nc_off; if ( n > 0x0F ) return( MBEDTLS_ERR_AES_BAD_INPUT_DATA ); @@ -1757,7 +1841,7 @@ int mbedtls_aes_self_test( int verbose ) * there is an alternative underlying implementation i.e. when * MBEDTLS_AES_ALT is defined. */ - if( ret == MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE && keybits == 192 ) + if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192 ) { mbedtls_printf( "skipped\n" ); continue; @@ -1821,7 +1905,7 @@ int mbedtls_aes_self_test( int verbose ) * there is an alternative underlying implementation i.e. when * MBEDTLS_AES_ALT is defined. */ - if( ret == MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE && keybits == 192 ) + if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192 ) { mbedtls_printf( "skipped\n" ); continue; @@ -1886,7 +1970,7 @@ int mbedtls_aes_self_test( int verbose ) * there is an alternative underlying implementation i.e. when * MBEDTLS_AES_ALT is defined. */ - if( ret == MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE && keybits == 192 ) + if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192 ) { mbedtls_printf( "skipped\n" ); continue; @@ -1949,7 +2033,7 @@ int mbedtls_aes_self_test( int verbose ) * there is an alternative underlying implementation i.e. when * MBEDTLS_AES_ALT is defined. */ - if( ret == MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE && keybits == 192 ) + if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192 ) { mbedtls_printf( "skipped\n" ); continue; diff --git a/thirdparty/mbedtls/library/aria.c b/thirdparty/mbedtls/library/aria.c index e9bcd6d135..aff66d667f 100644 --- a/thirdparty/mbedtls/library/aria.c +++ b/thirdparty/mbedtls/library/aria.c @@ -55,6 +55,12 @@ #define inline __inline #endif +/* Parameter validation macros */ +#define ARIA_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ARIA_BAD_INPUT_DATA ) +#define ARIA_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + /* * 32-bit integer manipulation macros (little endian) */ @@ -449,9 +455,11 @@ int mbedtls_aria_setkey_enc( mbedtls_aria_context *ctx, int i; uint32_t w[4][4], *w2; + ARIA_VALIDATE_RET( ctx != NULL ); + ARIA_VALIDATE_RET( key != NULL ); if( keybits != 128 && keybits != 192 && keybits != 256 ) - return( MBEDTLS_ERR_ARIA_INVALID_KEY_LENGTH ); + return( MBEDTLS_ERR_ARIA_BAD_INPUT_DATA ); /* Copy key to W0 (and potential remainder to W1) */ GET_UINT32_LE( w[0][0], key, 0 ); @@ -503,6 +511,8 @@ int mbedtls_aria_setkey_dec( mbedtls_aria_context *ctx, const unsigned char *key, unsigned int keybits ) { int i, j, k, ret; + ARIA_VALIDATE_RET( ctx != NULL ); + ARIA_VALIDATE_RET( key != NULL ); ret = mbedtls_aria_setkey_enc( ctx, key, keybits ); if( ret != 0 ) @@ -539,6 +549,9 @@ int mbedtls_aria_crypt_ecb( mbedtls_aria_context *ctx, int i; uint32_t a, b, c, d; + ARIA_VALIDATE_RET( ctx != NULL ); + ARIA_VALIDATE_RET( input != NULL ); + ARIA_VALIDATE_RET( output != NULL ); GET_UINT32_LE( a, input, 0 ); GET_UINT32_LE( b, input, 4 ); @@ -586,6 +599,7 @@ int mbedtls_aria_crypt_ecb( mbedtls_aria_context *ctx, /* Initialize context */ void mbedtls_aria_init( mbedtls_aria_context *ctx ) { + ARIA_VALIDATE( ctx != NULL ); memset( ctx, 0, sizeof( mbedtls_aria_context ) ); } @@ -612,6 +626,13 @@ int mbedtls_aria_crypt_cbc( mbedtls_aria_context *ctx, int i; unsigned char temp[MBEDTLS_ARIA_BLOCKSIZE]; + ARIA_VALIDATE_RET( ctx != NULL ); + ARIA_VALIDATE_RET( mode == MBEDTLS_ARIA_ENCRYPT || + mode == MBEDTLS_ARIA_DECRYPT ); + ARIA_VALIDATE_RET( length == 0 || input != NULL ); + ARIA_VALIDATE_RET( length == 0 || output != NULL ); + ARIA_VALIDATE_RET( iv != NULL ); + if( length % MBEDTLS_ARIA_BLOCKSIZE ) return( MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH ); @@ -665,7 +686,23 @@ int mbedtls_aria_crypt_cfb128( mbedtls_aria_context *ctx, unsigned char *output ) { unsigned char c; - size_t n = *iv_off; + size_t n; + + ARIA_VALIDATE_RET( ctx != NULL ); + ARIA_VALIDATE_RET( mode == MBEDTLS_ARIA_ENCRYPT || + mode == MBEDTLS_ARIA_DECRYPT ); + ARIA_VALIDATE_RET( length == 0 || input != NULL ); + ARIA_VALIDATE_RET( length == 0 || output != NULL ); + ARIA_VALIDATE_RET( iv != NULL ); + ARIA_VALIDATE_RET( iv_off != NULL ); + + n = *iv_off; + + /* An overly large value of n can lead to an unlimited + * buffer overflow. Therefore, guard against this + * outside of parameter validation. */ + if( n >= MBEDTLS_ARIA_BLOCKSIZE ) + return( MBEDTLS_ERR_ARIA_BAD_INPUT_DATA ); if( mode == MBEDTLS_ARIA_DECRYPT ) { @@ -713,7 +750,21 @@ int mbedtls_aria_crypt_ctr( mbedtls_aria_context *ctx, unsigned char *output ) { int c, i; - size_t n = *nc_off; + size_t n; + + ARIA_VALIDATE_RET( ctx != NULL ); + ARIA_VALIDATE_RET( length == 0 || input != NULL ); + ARIA_VALIDATE_RET( length == 0 || output != NULL ); + ARIA_VALIDATE_RET( nonce_counter != NULL ); + ARIA_VALIDATE_RET( stream_block != NULL ); + ARIA_VALIDATE_RET( nc_off != NULL ); + + n = *nc_off; + /* An overly large value of n can lead to an unlimited + * buffer overflow. Therefore, guard against this + * outside of parameter validation. */ + if( n >= MBEDTLS_ARIA_BLOCKSIZE ) + return( MBEDTLS_ERR_ARIA_BAD_INPUT_DATA ); while( length-- ) { @@ -875,11 +926,11 @@ static const uint8_t aria_test2_ctr_ct[3][48] = // CTR ciphertext #define ARIA_SELF_TEST_IF_FAIL \ { \ if( verbose ) \ - printf( "failed\n" ); \ + mbedtls_printf( "failed\n" ); \ return( 1 ); \ } else { \ if( verbose ) \ - printf( "passed\n" ); \ + mbedtls_printf( "passed\n" ); \ } /* @@ -908,7 +959,7 @@ int mbedtls_aria_self_test( int verbose ) { /* test ECB encryption */ if( verbose ) - printf( " ARIA-ECB-%d (enc): ", 128 + 64 * i ); + mbedtls_printf( " ARIA-ECB-%d (enc): ", 128 + 64 * i ); mbedtls_aria_setkey_enc( &ctx, aria_test1_ecb_key, 128 + 64 * i ); mbedtls_aria_crypt_ecb( &ctx, aria_test1_ecb_pt, blk ); if( memcmp( blk, aria_test1_ecb_ct[i], MBEDTLS_ARIA_BLOCKSIZE ) != 0 ) @@ -916,14 +967,14 @@ int mbedtls_aria_self_test( int verbose ) /* test ECB decryption */ if( verbose ) - printf( " ARIA-ECB-%d (dec): ", 128 + 64 * i ); + mbedtls_printf( " ARIA-ECB-%d (dec): ", 128 + 64 * i ); mbedtls_aria_setkey_dec( &ctx, aria_test1_ecb_key, 128 + 64 * i ); mbedtls_aria_crypt_ecb( &ctx, aria_test1_ecb_ct[i], blk ); if( memcmp( blk, aria_test1_ecb_pt, MBEDTLS_ARIA_BLOCKSIZE ) != 0 ) ARIA_SELF_TEST_IF_FAIL; } if( verbose ) - printf( "\n" ); + mbedtls_printf( "\n" ); /* * Test set 2 @@ -933,7 +984,7 @@ int mbedtls_aria_self_test( int verbose ) { /* Test CBC encryption */ if( verbose ) - printf( " ARIA-CBC-%d (enc): ", 128 + 64 * i ); + mbedtls_printf( " ARIA-CBC-%d (enc): ", 128 + 64 * i ); mbedtls_aria_setkey_enc( &ctx, aria_test2_key, 128 + 64 * i ); memcpy( iv, aria_test2_iv, MBEDTLS_ARIA_BLOCKSIZE ); memset( buf, 0x55, sizeof( buf ) ); @@ -944,7 +995,7 @@ int mbedtls_aria_self_test( int verbose ) /* Test CBC decryption */ if( verbose ) - printf( " ARIA-CBC-%d (dec): ", 128 + 64 * i ); + mbedtls_printf( " ARIA-CBC-%d (dec): ", 128 + 64 * i ); mbedtls_aria_setkey_dec( &ctx, aria_test2_key, 128 + 64 * i ); memcpy( iv, aria_test2_iv, MBEDTLS_ARIA_BLOCKSIZE ); memset( buf, 0xAA, sizeof( buf ) ); @@ -954,7 +1005,7 @@ int mbedtls_aria_self_test( int verbose ) ARIA_SELF_TEST_IF_FAIL; } if( verbose ) - printf( "\n" ); + mbedtls_printf( "\n" ); #endif /* MBEDTLS_CIPHER_MODE_CBC */ @@ -963,7 +1014,7 @@ int mbedtls_aria_self_test( int verbose ) { /* Test CFB encryption */ if( verbose ) - printf( " ARIA-CFB-%d (enc): ", 128 + 64 * i ); + mbedtls_printf( " ARIA-CFB-%d (enc): ", 128 + 64 * i ); mbedtls_aria_setkey_enc( &ctx, aria_test2_key, 128 + 64 * i ); memcpy( iv, aria_test2_iv, MBEDTLS_ARIA_BLOCKSIZE ); memset( buf, 0x55, sizeof( buf ) ); @@ -975,7 +1026,7 @@ int mbedtls_aria_self_test( int verbose ) /* Test CFB decryption */ if( verbose ) - printf( " ARIA-CFB-%d (dec): ", 128 + 64 * i ); + mbedtls_printf( " ARIA-CFB-%d (dec): ", 128 + 64 * i ); mbedtls_aria_setkey_enc( &ctx, aria_test2_key, 128 + 64 * i ); memcpy( iv, aria_test2_iv, MBEDTLS_ARIA_BLOCKSIZE ); memset( buf, 0xAA, sizeof( buf ) ); @@ -986,7 +1037,7 @@ int mbedtls_aria_self_test( int verbose ) ARIA_SELF_TEST_IF_FAIL; } if( verbose ) - printf( "\n" ); + mbedtls_printf( "\n" ); #endif /* MBEDTLS_CIPHER_MODE_CFB */ #if defined(MBEDTLS_CIPHER_MODE_CTR) @@ -994,7 +1045,7 @@ int mbedtls_aria_self_test( int verbose ) { /* Test CTR encryption */ if( verbose ) - printf( " ARIA-CTR-%d (enc): ", 128 + 64 * i ); + mbedtls_printf( " ARIA-CTR-%d (enc): ", 128 + 64 * i ); mbedtls_aria_setkey_enc( &ctx, aria_test2_key, 128 + 64 * i ); memset( iv, 0, MBEDTLS_ARIA_BLOCKSIZE ); // IV = 0 memset( buf, 0x55, sizeof( buf ) ); @@ -1006,7 +1057,7 @@ int mbedtls_aria_self_test( int verbose ) /* Test CTR decryption */ if( verbose ) - printf( " ARIA-CTR-%d (dec): ", 128 + 64 * i ); + mbedtls_printf( " ARIA-CTR-%d (dec): ", 128 + 64 * i ); mbedtls_aria_setkey_enc( &ctx, aria_test2_key, 128 + 64 * i ); memset( iv, 0, MBEDTLS_ARIA_BLOCKSIZE ); // IV = 0 memset( buf, 0xAA, sizeof( buf ) ); @@ -1017,7 +1068,7 @@ int mbedtls_aria_self_test( int verbose ) ARIA_SELF_TEST_IF_FAIL; } if( verbose ) - printf( "\n" ); + mbedtls_printf( "\n" ); #endif /* MBEDTLS_CIPHER_MODE_CTR */ return( 0 ); diff --git a/thirdparty/mbedtls/library/asn1write.c b/thirdparty/mbedtls/library/asn1write.c index 72acdf3012..a4d23f6196 100644 --- a/thirdparty/mbedtls/library/asn1write.c +++ b/thirdparty/mbedtls/library/asn1write.c @@ -257,34 +257,37 @@ int mbedtls_asn1_write_int( unsigned char **p, unsigned char *start, int val ) return( (int) len ); } -int mbedtls_asn1_write_printable_string( unsigned char **p, unsigned char *start, - const char *text, size_t text_len ) +int mbedtls_asn1_write_tagged_string( unsigned char **p, unsigned char *start, int tag, + const char *text, size_t text_len ) { int ret; size_t len = 0; MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, - (const unsigned char *) text, text_len ) ); + (const unsigned char *) text, text_len ) ); MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_PRINTABLE_STRING ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, tag ) ); return( (int) len ); } -int mbedtls_asn1_write_ia5_string( unsigned char **p, unsigned char *start, - const char *text, size_t text_len ) +int mbedtls_asn1_write_utf8_string( unsigned char **p, unsigned char *start, + const char *text, size_t text_len ) { - int ret; - size_t len = 0; - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, - (const unsigned char *) text, text_len ) ); + return( mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_UTF8_STRING, text, text_len) ); +} - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_IA5_STRING ) ); +int mbedtls_asn1_write_printable_string( unsigned char **p, unsigned char *start, + const char *text, size_t text_len ) +{ + return( mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_PRINTABLE_STRING, text, text_len) ); +} - return( (int) len ); +int mbedtls_asn1_write_ia5_string( unsigned char **p, unsigned char *start, + const char *text, size_t text_len ) +{ + return( mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_IA5_STRING, text, text_len) ); } int mbedtls_asn1_write_bitstring( unsigned char **p, unsigned char *start, @@ -328,14 +331,36 @@ int mbedtls_asn1_write_octet_string( unsigned char **p, unsigned char *start, return( (int) len ); } -mbedtls_asn1_named_data *mbedtls_asn1_store_named_data( mbedtls_asn1_named_data **head, + +/* This is a copy of the ASN.1 parsing function mbedtls_asn1_find_named_data(), + * which is replicated to avoid a dependency ASN1_WRITE_C on ASN1_PARSE_C. */ +static mbedtls_asn1_named_data *asn1_find_named_data( + mbedtls_asn1_named_data *list, + const char *oid, size_t len ) +{ + while( list != NULL ) + { + if( list->oid.len == len && + memcmp( list->oid.p, oid, len ) == 0 ) + { + break; + } + + list = list->next; + } + + return( list ); +} + +mbedtls_asn1_named_data *mbedtls_asn1_store_named_data( + mbedtls_asn1_named_data **head, const char *oid, size_t oid_len, const unsigned char *val, size_t val_len ) { mbedtls_asn1_named_data *cur; - if( ( cur = mbedtls_asn1_find_named_data( *head, oid, oid_len ) ) == NULL ) + if( ( cur = asn1_find_named_data( *head, oid, oid_len ) ) == NULL ) { // Add new entry if not present yet based on OID // diff --git a/thirdparty/mbedtls/library/bignum.c b/thirdparty/mbedtls/library/bignum.c index 423e375fd1..f968a0ad7d 100644 --- a/thirdparty/mbedtls/library/bignum.c +++ b/thirdparty/mbedtls/library/bignum.c @@ -59,6 +59,11 @@ #define mbedtls_free free #endif +#define MPI_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA ) +#define MPI_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + #define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */ #define biL (ciL << 3) /* bits in limb */ #define biH (ciL << 2) /* half limb size */ @@ -83,8 +88,7 @@ static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n ) */ void mbedtls_mpi_init( mbedtls_mpi *X ) { - if( X == NULL ) - return; + MPI_VALIDATE( X != NULL ); X->s = 1; X->n = 0; @@ -116,6 +120,7 @@ void mbedtls_mpi_free( mbedtls_mpi *X ) int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs ) { mbedtls_mpi_uint *p; + MPI_VALIDATE_RET( X != NULL ); if( nblimbs > MBEDTLS_MPI_MAX_LIMBS ) return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); @@ -147,6 +152,10 @@ int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs ) { mbedtls_mpi_uint *p; size_t i; + MPI_VALIDATE_RET( X != NULL ); + + if( nblimbs > MBEDTLS_MPI_MAX_LIMBS ) + return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); /* Actually resize up in this case */ if( X->n <= nblimbs ) @@ -183,6 +192,8 @@ int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y ) { int ret = 0; size_t i; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( Y != NULL ); if( X == Y ) return( 0 ); @@ -222,6 +233,8 @@ cleanup: void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y ) { mbedtls_mpi T; + MPI_VALIDATE( X != NULL ); + MPI_VALIDATE( Y != NULL ); memcpy( &T, X, sizeof( mbedtls_mpi ) ); memcpy( X, Y, sizeof( mbedtls_mpi ) ); @@ -237,6 +250,8 @@ int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned { int ret = 0; size_t i; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( Y != NULL ); /* make sure assign is 0 or 1 in a time-constant manner */ assign = (assign | (unsigned char)-assign) >> 7; @@ -266,6 +281,8 @@ int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char sw int ret, s; size_t i; mbedtls_mpi_uint tmp; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( Y != NULL ); if( X == Y ) return( 0 ); @@ -298,6 +315,7 @@ cleanup: int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z ) { int ret; + MPI_VALIDATE_RET( X != NULL ); MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) ); memset( X->p, 0, X->n * ciL ); @@ -315,12 +333,18 @@ cleanup: */ int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos ) { + MPI_VALIDATE_RET( X != NULL ); + if( X->n * biL <= pos ) return( 0 ); return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 ); } +/* Get a specific byte, without range checks. */ +#define GET_BYTE( X, i ) \ + ( ( ( X )->p[( i ) / ciL] >> ( ( ( i ) % ciL ) * 8 ) ) & 0xff ) + /* * Set a bit to a specific value of 0 or 1 */ @@ -329,6 +353,7 @@ int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val ) int ret = 0; size_t off = pos / biL; size_t idx = pos % biL; + MPI_VALIDATE_RET( X != NULL ); if( val != 0 && val != 1 ) return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); @@ -355,6 +380,7 @@ cleanup: size_t mbedtls_mpi_lsb( const mbedtls_mpi *X ) { size_t i, j, count = 0; + MBEDTLS_INTERNAL_VALIDATE_RET( X != NULL, 0 ); for( i = 0; i < X->n; i++ ) for( j = 0; j < biL; j++, count++ ) @@ -435,6 +461,8 @@ int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s ) size_t i, j, slen, n; mbedtls_mpi_uint d; mbedtls_mpi T; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( s != NULL ); if( radix < 2 || radix > 16 ) return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); @@ -535,6 +563,9 @@ int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix, size_t n; char *p; mbedtls_mpi T; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( olen != NULL ); + MPI_VALIDATE_RET( buflen == 0 || buf != NULL ); if( radix < 2 || radix > 16 ) return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); @@ -616,6 +647,12 @@ int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin ) */ char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ]; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( fin != NULL ); + + if( radix < 2 || radix > 16 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + memset( s, 0, sizeof( s ) ); if( fgets( s, sizeof( s ) - 1, fin ) == NULL ) return( MBEDTLS_ERR_MPI_FILE_IO_ERROR ); @@ -647,6 +684,10 @@ int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE * newline characters and '\0' */ char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ]; + MPI_VALIDATE_RET( X != NULL ); + + if( radix < 2 || radix > 16 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); memset( s, 0, sizeof( s ) ); @@ -683,6 +724,9 @@ int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t bu size_t i, j; size_t const limbs = CHARS_TO_LIMBS( buflen ); + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( buflen == 0 || buf != NULL ); + /* Ensure that target MPI has exactly the necessary number of limbs */ if( X->n != limbs ) { @@ -704,19 +748,45 @@ cleanup: /* * Export X into unsigned binary data, big endian */ -int mbedtls_mpi_write_binary( const mbedtls_mpi *X, unsigned char *buf, size_t buflen ) +int mbedtls_mpi_write_binary( const mbedtls_mpi *X, + unsigned char *buf, size_t buflen ) { - size_t i, j, n; + size_t stored_bytes; + size_t bytes_to_copy; + unsigned char *p; + size_t i; - n = mbedtls_mpi_size( X ); + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( buflen == 0 || buf != NULL ); - if( buflen < n ) - return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); + stored_bytes = X->n * ciL; - memset( buf, 0, buflen ); + if( stored_bytes < buflen ) + { + /* There is enough space in the output buffer. Write initial + * null bytes and record the position at which to start + * writing the significant bytes. In this case, the execution + * trace of this function does not depend on the value of the + * number. */ + bytes_to_copy = stored_bytes; + p = buf + buflen - stored_bytes; + memset( buf, 0, buflen - stored_bytes ); + } + else + { + /* The output buffer is smaller than the allocated size of X. + * However X may fit if its leading bytes are zero. */ + bytes_to_copy = buflen; + p = buf; + for( i = bytes_to_copy; i < stored_bytes; i++ ) + { + if( GET_BYTE( X, i ) != 0 ) + return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); + } + } - for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- ) - buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) ); + for( i = 0; i < bytes_to_copy; i++ ) + p[bytes_to_copy - i - 1] = GET_BYTE( X, i ); return( 0 ); } @@ -729,6 +799,7 @@ int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count ) int ret; size_t i, v0, t1; mbedtls_mpi_uint r0 = 0, r1; + MPI_VALIDATE_RET( X != NULL ); v0 = count / (biL ); t1 = count & (biL - 1); @@ -778,6 +849,7 @@ int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count ) { size_t i, v0, v1; mbedtls_mpi_uint r0 = 0, r1; + MPI_VALIDATE_RET( X != NULL ); v0 = count / biL; v1 = count & (biL - 1); @@ -820,6 +892,8 @@ int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count ) int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y ) { size_t i, j; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( Y != NULL ); for( i = X->n; i > 0; i-- ) if( X->p[i - 1] != 0 ) @@ -850,6 +924,8 @@ int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y ) int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y ) { size_t i, j; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( Y != NULL ); for( i = X->n; i > 0; i-- ) if( X->p[i - 1] != 0 ) @@ -884,6 +960,7 @@ int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z ) { mbedtls_mpi Y; mbedtls_mpi_uint p[1]; + MPI_VALIDATE_RET( X != NULL ); *p = ( z < 0 ) ? -z : z; Y.s = ( z < 0 ) ? -1 : 1; @@ -901,6 +978,9 @@ int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi int ret; size_t i, j; mbedtls_mpi_uint *o, *p, c, tmp; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( B != NULL ); if( X == B ) { @@ -978,6 +1058,9 @@ int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi mbedtls_mpi TB; int ret; size_t n; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( B != NULL ); if( mbedtls_mpi_cmp_abs( A, B ) < 0 ) return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE ); @@ -1018,8 +1101,12 @@ cleanup: */ int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) { - int ret, s = A->s; + int ret, s; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( B != NULL ); + s = A->s; if( A->s * B->s < 0 ) { if( mbedtls_mpi_cmp_abs( A, B ) >= 0 ) @@ -1049,8 +1136,12 @@ cleanup: */ int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) { - int ret, s = A->s; + int ret, s; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( B != NULL ); + s = A->s; if( A->s * B->s > 0 ) { if( mbedtls_mpi_cmp_abs( A, B ) >= 0 ) @@ -1082,6 +1173,8 @@ int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint { mbedtls_mpi _B; mbedtls_mpi_uint p[1]; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); p[0] = ( b < 0 ) ? -b : b; _B.s = ( b < 0 ) ? -1 : 1; @@ -1098,6 +1191,8 @@ int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint { mbedtls_mpi _B; mbedtls_mpi_uint p[1]; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); p[0] = ( b < 0 ) ? -b : b; _B.s = ( b < 0 ) ? -1 : 1; @@ -1187,6 +1282,9 @@ int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi int ret; size_t i, j; mbedtls_mpi TA, TB; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( B != NULL ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB ); @@ -1223,6 +1321,8 @@ int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint { mbedtls_mpi _B; mbedtls_mpi_uint p[1]; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); _B.s = 1; _B.n = 1; @@ -1331,11 +1431,14 @@ static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1, /* * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20) */ -int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B ) +int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, + const mbedtls_mpi *B ) { int ret; size_t i, n, t, k; mbedtls_mpi X, Y, Z, T1, T2; + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( B != NULL ); if( mbedtls_mpi_cmp_int( B, 0 ) == 0 ) return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO ); @@ -1446,10 +1549,13 @@ cleanup: /* * Division by int: A = Q * b + R */ -int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, mbedtls_mpi_sint b ) +int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R, + const mbedtls_mpi *A, + mbedtls_mpi_sint b ) { mbedtls_mpi _B; mbedtls_mpi_uint p[1]; + MPI_VALIDATE_RET( A != NULL ); p[0] = ( b < 0 ) ? -b : b; _B.s = ( b < 0 ) ? -1 : 1; @@ -1465,6 +1571,9 @@ int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, m int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B ) { int ret; + MPI_VALIDATE_RET( R != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( B != NULL ); if( mbedtls_mpi_cmp_int( B, 0 ) < 0 ) return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE ); @@ -1489,6 +1598,8 @@ int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_ { size_t i; mbedtls_mpi_uint x, y, z; + MPI_VALIDATE_RET( r != NULL ); + MPI_VALIDATE_RET( A != NULL ); if( b == 0 ) return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO ); @@ -1602,7 +1713,8 @@ static int mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi /* * Montgomery reduction: A = A * R^-1 mod N */ -static int mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N, mbedtls_mpi_uint mm, const mbedtls_mpi *T ) +static int mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N, + mbedtls_mpi_uint mm, const mbedtls_mpi *T ) { mbedtls_mpi_uint z = 1; mbedtls_mpi U; @@ -1616,7 +1728,9 @@ static int mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N, mbedtls_mpi_uint m /* * Sliding-window exponentiation: X = A^E mod N (HAC 14.85) */ -int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *E, const mbedtls_mpi *N, mbedtls_mpi *_RR ) +int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *E, const mbedtls_mpi *N, + mbedtls_mpi *_RR ) { int ret; size_t wbits, wsize, one = 1; @@ -1626,6 +1740,11 @@ int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos; int neg; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( E != NULL ); + MPI_VALIDATE_RET( N != NULL ); + if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 ) return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); @@ -1830,6 +1949,10 @@ int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B size_t lz, lzt; mbedtls_mpi TG, TA, TB; + MPI_VALIDATE_RET( G != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( B != NULL ); + mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB ); MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); @@ -1886,6 +2009,8 @@ int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size, { int ret; unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( f_rng != NULL ); if( size > MBEDTLS_MPI_MAX_SIZE ) return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); @@ -1905,6 +2030,9 @@ int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi { int ret; mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( N != NULL ); if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 ) return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); @@ -2056,15 +2184,19 @@ cleanup: /* * Miller-Rabin pseudo-primality test (HAC 4.24) */ -static int mpi_miller_rabin( const mbedtls_mpi *X, +static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { int ret, count; - size_t i, j, k, n, s; + size_t i, j, k, s; mbedtls_mpi W, R, T, A, RR; - mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A ); + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( f_rng != NULL ); + + mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); + mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A ); mbedtls_mpi_init( &RR ); /* @@ -2077,27 +2209,12 @@ static int mpi_miller_rabin( const mbedtls_mpi *X, MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) ); i = mbedtls_mpi_bitlen( X ); - /* - * HAC, table 4.4 - */ - n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 : - ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 : - ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 ); - for( i = 0; i < n; i++ ) + for( i = 0; i < rounds; i++ ) { /* * pick a random A, 1 < A < |X| - 1 */ - MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) ); - - if( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ) - { - j = mbedtls_mpi_bitlen( &A ) - mbedtls_mpi_bitlen( &W ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j + 1 ) ); - } - A.p[0] |= 3; - count = 0; do { MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) ); @@ -2105,7 +2222,7 @@ static int mpi_miller_rabin( const mbedtls_mpi *X, j = mbedtls_mpi_bitlen( &A ); k = mbedtls_mpi_bitlen( &W ); if (j > k) { - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j - k ) ); + A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1; } if (count++ > 30) { @@ -2151,7 +2268,8 @@ static int mpi_miller_rabin( const mbedtls_mpi *X, } cleanup: - mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A ); + mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); + mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A ); mbedtls_mpi_free( &RR ); return( ret ); @@ -2160,12 +2278,14 @@ cleanup: /* * Pseudo-primality test: small factors, then Miller-Rabin */ -int mbedtls_mpi_is_prime( const mbedtls_mpi *X, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) +int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) { int ret; mbedtls_mpi XX; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( f_rng != NULL ); XX.s = 1; XX.n = X->n; @@ -2186,17 +2306,37 @@ int mbedtls_mpi_is_prime( const mbedtls_mpi *X, return( ret ); } - return( mpi_miller_rabin( &XX, f_rng, p_rng ) ); + return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +/* + * Pseudo-primality test, error probability 2^-80 + */ +int mbedtls_mpi_is_prime( const mbedtls_mpi *X, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( f_rng != NULL ); + + /* + * In the past our key generation aimed for an error rate of at most + * 2^-80. Since this function is deprecated, aim for the same certainty + * here as well. + */ + return( mbedtls_mpi_is_prime_ext( X, 40, f_rng, p_rng ) ); } +#endif /* * Prime number generation * - * If dh_flag is 0 and nbits is at least 1024, then the procedure - * follows the RSA probably-prime generation method of FIPS 186-4. - * NB. FIPS 186-4 only allows the specific bit lengths of 1024 and 1536. + * To generate an RSA key in a way recommended by FIPS 186-4, both primes must + * be either 1024 bits or 1536 bits long, and flags must contain + * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR. */ -int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag, +int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { @@ -2209,9 +2349,13 @@ int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag, #endif int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; size_t k, n; + int rounds; mbedtls_mpi_uint r; mbedtls_mpi Y; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( f_rng != NULL ); + if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS ) return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); @@ -2219,6 +2363,27 @@ int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag, n = BITS_TO_LIMBS( nbits ); + if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR ) == 0 ) + { + /* + * 2^-80 error probability, number of rounds chosen per HAC, table 4.4 + */ + rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 : + ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 : + ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 ); + } + else + { + /* + * 2^-100 error probability, number of rounds computed based on HAC, + * fact 4.48 + */ + rounds = ( ( nbits >= 1450 ) ? 4 : ( nbits >= 1150 ) ? 5 : + ( nbits >= 1000 ) ? 6 : ( nbits >= 850 ) ? 7 : + ( nbits >= 750 ) ? 8 : ( nbits >= 500 ) ? 13 : + ( nbits >= 250 ) ? 28 : ( nbits >= 150 ) ? 40 : 51 ); + } + while( 1 ) { MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) ); @@ -2229,9 +2394,9 @@ int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag, if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) ); X->p[0] |= 1; - if( dh_flag == 0 ) + if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH ) == 0 ) { - ret = mbedtls_mpi_is_prime( X, f_rng, p_rng ); + ret = mbedtls_mpi_is_prime_ext( X, rounds, f_rng, p_rng ); if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ) goto cleanup; @@ -2264,8 +2429,10 @@ int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag, */ if( ( ret = mpi_check_small_factors( X ) ) == 0 && ( ret = mpi_check_small_factors( &Y ) ) == 0 && - ( ret = mpi_miller_rabin( X, f_rng, p_rng ) ) == 0 && - ( ret = mpi_miller_rabin( &Y, f_rng, p_rng ) ) == 0 ) + ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) ) + == 0 && + ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) ) + == 0 ) goto cleanup; if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ) diff --git a/thirdparty/mbedtls/library/blowfish.c b/thirdparty/mbedtls/library/blowfish.c index 5b6bb9885f..cbf9238246 100644 --- a/thirdparty/mbedtls/library/blowfish.c +++ b/thirdparty/mbedtls/library/blowfish.c @@ -40,6 +40,12 @@ #if !defined(MBEDTLS_BLOWFISH_ALT) +/* Parameter validation macros */ +#define BLOWFISH_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA ) +#define BLOWFISH_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + /* * 32-bit integer manipulation macros (big endian) */ @@ -153,6 +159,7 @@ static void blowfish_dec( mbedtls_blowfish_context *ctx, uint32_t *xl, uint32_t void mbedtls_blowfish_init( mbedtls_blowfish_context *ctx ) { + BLOWFISH_VALIDATE( ctx != NULL ); memset( ctx, 0, sizeof( mbedtls_blowfish_context ) ); } @@ -167,16 +174,20 @@ void mbedtls_blowfish_free( mbedtls_blowfish_context *ctx ) /* * Blowfish key schedule */ -int mbedtls_blowfish_setkey( mbedtls_blowfish_context *ctx, const unsigned char *key, - unsigned int keybits ) +int mbedtls_blowfish_setkey( mbedtls_blowfish_context *ctx, + const unsigned char *key, + unsigned int keybits ) { unsigned int i, j, k; uint32_t data, datal, datar; + BLOWFISH_VALIDATE_RET( ctx != NULL ); + BLOWFISH_VALIDATE_RET( key != NULL ); - if( keybits < MBEDTLS_BLOWFISH_MIN_KEY_BITS || keybits > MBEDTLS_BLOWFISH_MAX_KEY_BITS || - ( keybits % 8 ) ) + if( keybits < MBEDTLS_BLOWFISH_MIN_KEY_BITS || + keybits > MBEDTLS_BLOWFISH_MAX_KEY_BITS || + keybits % 8 != 0 ) { - return( MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH ); + return( MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA ); } keybits >>= 3; @@ -231,6 +242,11 @@ int mbedtls_blowfish_crypt_ecb( mbedtls_blowfish_context *ctx, unsigned char output[MBEDTLS_BLOWFISH_BLOCKSIZE] ) { uint32_t X0, X1; + BLOWFISH_VALIDATE_RET( ctx != NULL ); + BLOWFISH_VALIDATE_RET( mode == MBEDTLS_BLOWFISH_ENCRYPT || + mode == MBEDTLS_BLOWFISH_DECRYPT ); + BLOWFISH_VALIDATE_RET( input != NULL ); + BLOWFISH_VALIDATE_RET( output != NULL ); GET_UINT32_BE( X0, input, 0 ); GET_UINT32_BE( X1, input, 4 ); @@ -263,6 +279,12 @@ int mbedtls_blowfish_crypt_cbc( mbedtls_blowfish_context *ctx, { int i; unsigned char temp[MBEDTLS_BLOWFISH_BLOCKSIZE]; + BLOWFISH_VALIDATE_RET( ctx != NULL ); + BLOWFISH_VALIDATE_RET( mode == MBEDTLS_BLOWFISH_ENCRYPT || + mode == MBEDTLS_BLOWFISH_DECRYPT ); + BLOWFISH_VALIDATE_RET( iv != NULL ); + BLOWFISH_VALIDATE_RET( length == 0 || input != NULL ); + BLOWFISH_VALIDATE_RET( length == 0 || output != NULL ); if( length % MBEDTLS_BLOWFISH_BLOCKSIZE ) return( MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH ); @@ -317,7 +339,19 @@ int mbedtls_blowfish_crypt_cfb64( mbedtls_blowfish_context *ctx, unsigned char *output ) { int c; - size_t n = *iv_off; + size_t n; + + BLOWFISH_VALIDATE_RET( ctx != NULL ); + BLOWFISH_VALIDATE_RET( mode == MBEDTLS_BLOWFISH_ENCRYPT || + mode == MBEDTLS_BLOWFISH_DECRYPT ); + BLOWFISH_VALIDATE_RET( iv != NULL ); + BLOWFISH_VALIDATE_RET( iv_off != NULL ); + BLOWFISH_VALIDATE_RET( length == 0 || input != NULL ); + BLOWFISH_VALIDATE_RET( length == 0 || output != NULL ); + + n = *iv_off; + if( n >= 8 ) + return( MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA ); if( mode == MBEDTLS_BLOWFISH_DECRYPT ) { @@ -365,7 +399,17 @@ int mbedtls_blowfish_crypt_ctr( mbedtls_blowfish_context *ctx, unsigned char *output ) { int c, i; - size_t n = *nc_off; + size_t n; + BLOWFISH_VALIDATE_RET( ctx != NULL ); + BLOWFISH_VALIDATE_RET( nonce_counter != NULL ); + BLOWFISH_VALIDATE_RET( stream_block != NULL ); + BLOWFISH_VALIDATE_RET( nc_off != NULL ); + BLOWFISH_VALIDATE_RET( length == 0 || input != NULL ); + BLOWFISH_VALIDATE_RET( length == 0 || output != NULL ); + + n = *nc_off; + if( n >= 8 ) + return( MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA ); while( length-- ) { diff --git a/thirdparty/mbedtls/library/camellia.c b/thirdparty/mbedtls/library/camellia.c index 41b7da0fae..22262b89a8 100644 --- a/thirdparty/mbedtls/library/camellia.c +++ b/thirdparty/mbedtls/library/camellia.c @@ -49,6 +49,12 @@ #if !defined(MBEDTLS_CAMELLIA_ALT) +/* Parameter validation macros */ +#define CAMELLIA_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA ) +#define CAMELLIA_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + /* * 32-bit integer manipulation macros (big endian) */ @@ -321,6 +327,7 @@ static void camellia_feistel( const uint32_t x[2], const uint32_t k[2], void mbedtls_camellia_init( mbedtls_camellia_context *ctx ) { + CAMELLIA_VALIDATE( ctx != NULL ); memset( ctx, 0, sizeof( mbedtls_camellia_context ) ); } @@ -335,8 +342,9 @@ void mbedtls_camellia_free( mbedtls_camellia_context *ctx ) /* * Camellia key schedule (encryption) */ -int mbedtls_camellia_setkey_enc( mbedtls_camellia_context *ctx, const unsigned char *key, - unsigned int keybits ) +int mbedtls_camellia_setkey_enc( mbedtls_camellia_context *ctx, + const unsigned char *key, + unsigned int keybits ) { int idx; size_t i; @@ -346,6 +354,9 @@ int mbedtls_camellia_setkey_enc( mbedtls_camellia_context *ctx, const unsigned c uint32_t KC[16]; uint32_t TK[20]; + CAMELLIA_VALIDATE_RET( ctx != NULL ); + CAMELLIA_VALIDATE_RET( key != NULL ); + RK = ctx->rk; memset( t, 0, 64 ); @@ -356,7 +367,7 @@ int mbedtls_camellia_setkey_enc( mbedtls_camellia_context *ctx, const unsigned c case 128: ctx->nr = 3; idx = 0; break; case 192: case 256: ctx->nr = 4; idx = 1; break; - default : return( MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH ); + default : return( MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA ); } for( i = 0; i < keybits / 8; ++i ) @@ -440,14 +451,17 @@ int mbedtls_camellia_setkey_enc( mbedtls_camellia_context *ctx, const unsigned c /* * Camellia key schedule (decryption) */ -int mbedtls_camellia_setkey_dec( mbedtls_camellia_context *ctx, const unsigned char *key, - unsigned int keybits ) +int mbedtls_camellia_setkey_dec( mbedtls_camellia_context *ctx, + const unsigned char *key, + unsigned int keybits ) { int idx, ret; size_t i; mbedtls_camellia_context cty; uint32_t *RK; uint32_t *SK; + CAMELLIA_VALIDATE_RET( ctx != NULL ); + CAMELLIA_VALIDATE_RET( key != NULL ); mbedtls_camellia_init( &cty ); @@ -495,6 +509,11 @@ int mbedtls_camellia_crypt_ecb( mbedtls_camellia_context *ctx, { int NR; uint32_t *RK, X[4]; + CAMELLIA_VALIDATE_RET( ctx != NULL ); + CAMELLIA_VALIDATE_RET( mode == MBEDTLS_CAMELLIA_ENCRYPT || + mode == MBEDTLS_CAMELLIA_DECRYPT ); + CAMELLIA_VALIDATE_RET( input != NULL ); + CAMELLIA_VALIDATE_RET( output != NULL ); ( (void) mode ); @@ -552,14 +571,20 @@ int mbedtls_camellia_crypt_ecb( mbedtls_camellia_context *ctx, * Camellia-CBC buffer encryption/decryption */ int mbedtls_camellia_crypt_cbc( mbedtls_camellia_context *ctx, - int mode, - size_t length, - unsigned char iv[16], - const unsigned char *input, - unsigned char *output ) + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) { int i; unsigned char temp[16]; + CAMELLIA_VALIDATE_RET( ctx != NULL ); + CAMELLIA_VALIDATE_RET( mode == MBEDTLS_CAMELLIA_ENCRYPT || + mode == MBEDTLS_CAMELLIA_DECRYPT ); + CAMELLIA_VALIDATE_RET( iv != NULL ); + CAMELLIA_VALIDATE_RET( length == 0 || input != NULL ); + CAMELLIA_VALIDATE_RET( length == 0 || output != NULL ); if( length % 16 ) return( MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH ); @@ -614,7 +639,18 @@ int mbedtls_camellia_crypt_cfb128( mbedtls_camellia_context *ctx, unsigned char *output ) { int c; - size_t n = *iv_off; + size_t n; + CAMELLIA_VALIDATE_RET( ctx != NULL ); + CAMELLIA_VALIDATE_RET( mode == MBEDTLS_CAMELLIA_ENCRYPT || + mode == MBEDTLS_CAMELLIA_DECRYPT ); + CAMELLIA_VALIDATE_RET( iv != NULL ); + CAMELLIA_VALIDATE_RET( iv_off != NULL ); + CAMELLIA_VALIDATE_RET( length == 0 || input != NULL ); + CAMELLIA_VALIDATE_RET( length == 0 || output != NULL ); + + n = *iv_off; + if( n >= 16 ) + return( MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA ); if( mode == MBEDTLS_CAMELLIA_DECRYPT ) { @@ -662,7 +698,17 @@ int mbedtls_camellia_crypt_ctr( mbedtls_camellia_context *ctx, unsigned char *output ) { int c, i; - size_t n = *nc_off; + size_t n; + CAMELLIA_VALIDATE_RET( ctx != NULL ); + CAMELLIA_VALIDATE_RET( nonce_counter != NULL ); + CAMELLIA_VALIDATE_RET( stream_block != NULL ); + CAMELLIA_VALIDATE_RET( nc_off != NULL ); + CAMELLIA_VALIDATE_RET( length == 0 || input != NULL ); + CAMELLIA_VALIDATE_RET( length == 0 || output != NULL ); + + n = *nc_off; + if( n >= 16 ) + return( MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA ); while( length-- ) { diff --git a/thirdparty/mbedtls/library/ccm.c b/thirdparty/mbedtls/library/ccm.c index 804eaf80f1..01e58b0436 100644 --- a/thirdparty/mbedtls/library/ccm.c +++ b/thirdparty/mbedtls/library/ccm.c @@ -52,6 +52,11 @@ #if !defined(MBEDTLS_CCM_ALT) +#define CCM_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_CCM_BAD_INPUT ) +#define CCM_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + #define CCM_ENCRYPT 0 #define CCM_DECRYPT 1 @@ -60,6 +65,7 @@ */ void mbedtls_ccm_init( mbedtls_ccm_context *ctx ) { + CCM_VALIDATE( ctx != NULL ); memset( ctx, 0, sizeof( mbedtls_ccm_context ) ); } @@ -71,6 +77,9 @@ int mbedtls_ccm_setkey( mbedtls_ccm_context *ctx, int ret; const mbedtls_cipher_info_t *cipher_info; + CCM_VALIDATE_RET( ctx != NULL ); + CCM_VALIDATE_RET( key != NULL ); + cipher_info = mbedtls_cipher_info_from_values( cipher, keybits, MBEDTLS_MODE_ECB ); if( cipher_info == NULL ) return( MBEDTLS_ERR_CCM_BAD_INPUT ); @@ -97,6 +106,8 @@ int mbedtls_ccm_setkey( mbedtls_ccm_context *ctx, */ void mbedtls_ccm_free( mbedtls_ccm_context *ctx ) { + if( ctx == NULL ) + return; mbedtls_cipher_free( &ctx->cipher_ctx ); mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ccm_context ) ); } @@ -310,6 +321,12 @@ int mbedtls_ccm_star_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length, const unsigned char *input, unsigned char *output, unsigned char *tag, size_t tag_len ) { + CCM_VALIDATE_RET( ctx != NULL ); + CCM_VALIDATE_RET( iv != NULL ); + CCM_VALIDATE_RET( add_len == 0 || add != NULL ); + CCM_VALIDATE_RET( length == 0 || input != NULL ); + CCM_VALIDATE_RET( length == 0 || output != NULL ); + CCM_VALIDATE_RET( tag_len == 0 || tag != NULL ); return( ccm_auth_crypt( ctx, CCM_ENCRYPT, length, iv, iv_len, add, add_len, input, output, tag, tag_len ) ); } @@ -320,6 +337,12 @@ int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length, const unsigned char *input, unsigned char *output, unsigned char *tag, size_t tag_len ) { + CCM_VALIDATE_RET( ctx != NULL ); + CCM_VALIDATE_RET( iv != NULL ); + CCM_VALIDATE_RET( add_len == 0 || add != NULL ); + CCM_VALIDATE_RET( length == 0 || input != NULL ); + CCM_VALIDATE_RET( length == 0 || output != NULL ); + CCM_VALIDATE_RET( tag_len == 0 || tag != NULL ); if( tag_len == 0 ) return( MBEDTLS_ERR_CCM_BAD_INPUT ); @@ -341,6 +364,13 @@ int mbedtls_ccm_star_auth_decrypt( mbedtls_ccm_context *ctx, size_t length, unsigned char i; int diff; + CCM_VALIDATE_RET( ctx != NULL ); + CCM_VALIDATE_RET( iv != NULL ); + CCM_VALIDATE_RET( add_len == 0 || add != NULL ); + CCM_VALIDATE_RET( length == 0 || input != NULL ); + CCM_VALIDATE_RET( length == 0 || output != NULL ); + CCM_VALIDATE_RET( tag_len == 0 || tag != NULL ); + if( ( ret = ccm_auth_crypt( ctx, CCM_DECRYPT, length, iv, iv_len, add, add_len, input, output, check_tag, tag_len ) ) != 0 ) @@ -367,6 +397,13 @@ int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length, const unsigned char *input, unsigned char *output, const unsigned char *tag, size_t tag_len ) { + CCM_VALIDATE_RET( ctx != NULL ); + CCM_VALIDATE_RET( iv != NULL ); + CCM_VALIDATE_RET( add_len == 0 || add != NULL ); + CCM_VALIDATE_RET( length == 0 || input != NULL ); + CCM_VALIDATE_RET( length == 0 || output != NULL ); + CCM_VALIDATE_RET( tag_len == 0 || tag != NULL ); + if( tag_len == 0 ) return( MBEDTLS_ERR_CCM_BAD_INPUT ); @@ -381,7 +418,8 @@ int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length, */ #define NB_TESTS 3 - +#define CCM_SELFTEST_PT_MAX_LEN 24 +#define CCM_SELFTEST_CT_MAX_LEN 32 /* * The data is the same for all tests, only the used length changes */ @@ -401,7 +439,7 @@ static const unsigned char ad[] = { 0x10, 0x11, 0x12, 0x13 }; -static const unsigned char msg[] = { +static const unsigned char msg[CCM_SELFTEST_PT_MAX_LEN] = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, @@ -412,7 +450,7 @@ static const size_t add_len[NB_TESTS] = { 8, 16, 20 }; static const size_t msg_len[NB_TESTS] = { 4, 16, 24 }; static const size_t tag_len[NB_TESTS] = { 4, 6, 8 }; -static const unsigned char res[NB_TESTS][32] = { +static const unsigned char res[NB_TESTS][CCM_SELFTEST_CT_MAX_LEN] = { { 0x71, 0x62, 0x01, 0x5b, 0x4d, 0xac, 0x25, 0x5d }, { 0xd2, 0xa1, 0xf0, 0xe0, 0x51, 0xea, 0x5f, 0x62, 0x08, 0x1a, 0x77, 0x92, 0x07, 0x3d, 0x59, 0x3d, @@ -426,7 +464,13 @@ static const unsigned char res[NB_TESTS][32] = { int mbedtls_ccm_self_test( int verbose ) { mbedtls_ccm_context ctx; - unsigned char out[32]; + /* + * Some hardware accelerators require the input and output buffers + * would be in RAM, because the flash is not accessible. + * Use buffers on the stack to hold the test vectors data. + */ + unsigned char plaintext[CCM_SELFTEST_PT_MAX_LEN]; + unsigned char ciphertext[CCM_SELFTEST_CT_MAX_LEN]; size_t i; int ret; @@ -445,27 +489,32 @@ int mbedtls_ccm_self_test( int verbose ) if( verbose != 0 ) mbedtls_printf( " CCM-AES #%u: ", (unsigned int) i + 1 ); + memset( plaintext, 0, CCM_SELFTEST_PT_MAX_LEN ); + memset( ciphertext, 0, CCM_SELFTEST_CT_MAX_LEN ); + memcpy( plaintext, msg, msg_len[i] ); + ret = mbedtls_ccm_encrypt_and_tag( &ctx, msg_len[i], - iv, iv_len[i], ad, add_len[i], - msg, out, - out + msg_len[i], tag_len[i] ); + iv, iv_len[i], ad, add_len[i], + plaintext, ciphertext, + ciphertext + msg_len[i], tag_len[i] ); if( ret != 0 || - memcmp( out, res[i], msg_len[i] + tag_len[i] ) != 0 ) + memcmp( ciphertext, res[i], msg_len[i] + tag_len[i] ) != 0 ) { if( verbose != 0 ) mbedtls_printf( "failed\n" ); return( 1 ); } + memset( plaintext, 0, CCM_SELFTEST_PT_MAX_LEN ); ret = mbedtls_ccm_auth_decrypt( &ctx, msg_len[i], - iv, iv_len[i], ad, add_len[i], - res[i], out, - res[i] + msg_len[i], tag_len[i] ); + iv, iv_len[i], ad, add_len[i], + ciphertext, plaintext, + ciphertext + msg_len[i], tag_len[i] ); if( ret != 0 || - memcmp( out, msg, msg_len[i] ) != 0 ) + memcmp( plaintext, msg, msg_len[i] ) != 0 ) { if( verbose != 0 ) mbedtls_printf( "failed\n" ); diff --git a/thirdparty/mbedtls/library/certs.c b/thirdparty/mbedtls/library/certs.c index f1379b8cb1..ff0f11e923 100644 --- a/thirdparty/mbedtls/library/certs.c +++ b/thirdparty/mbedtls/library/certs.c @@ -218,12 +218,13 @@ const size_t mbedtls_test_ca_key_rsa_len = sizeof( mbedtls_test_ca_key_rsa ); const char mbedtls_test_ca_pwd_rsa[] = "PolarSSLTest"; const size_t mbedtls_test_ca_pwd_rsa_len = sizeof( mbedtls_test_ca_pwd_rsa ) - 1; +/* tests/data_files/server2.crt */ const char mbedtls_test_srv_crt_rsa[] = "-----BEGIN CERTIFICATE-----\r\n" "MIIDNzCCAh+gAwIBAgIBAjANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n" -"MA8GA1UEChMIUG9sYXJTU0wxGTAXBgNVBAMTEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" +"MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" "MTEwMjEyMTQ0NDA2WhcNMjEwMjEyMTQ0NDA2WjA0MQswCQYDVQQGEwJOTDERMA8G\r\n" -"A1UEChMIUG9sYXJTU0wxEjAQBgNVBAMTCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcN\r\n" +"A1UECgwIUG9sYXJTU0wxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcN\r\n" "AQEBBQADggEPADCCAQoCggEBAMFNo93nzR3RBNdJcriZrA545Do8Ss86ExbQWuTN\r\n" "owCIp+4ea5anUrSQ7y1yej4kmvy2NKwk9XfgJmSMnLAofaHa6ozmyRyWvP7BBFKz\r\n" "NtSj+uGxdtiQwWG0ZlI2oiZTqqt0Xgd9GYLbKtgfoNkNHC1JZvdbJXNG6AuKT2kM\r\n" @@ -231,16 +232,17 @@ const char mbedtls_test_srv_crt_rsa[] = "hYvai0Re4hjGYi/HZo36Xdh98yeJKQHFkA4/J/EwyEoO79bex8cna8cFPXrEAjya\r\n" "HT4P6DSYW8tzS1KW2BGiLICIaTla0w+w3lkvEcf36hIBMJcCAwEAAaNNMEswCQYD\r\n" "VR0TBAIwADAdBgNVHQ4EFgQUpQXoZLjc32APUBJNYKhkr02LQ5MwHwYDVR0jBBgw\r\n" -"FoAUtFrkpbPe0lL2udWmlQ/rPrzH/f8wDQYJKoZIhvcNAQEFBQADggEBAJxnXClY\r\n" -"oHkbp70cqBrsGXLybA74czbO5RdLEgFs7rHVS9r+c293luS/KdliLScZqAzYVylw\r\n" -"UfRWvKMoWhHYKp3dEIS4xTXk6/5zXxhv9Rw8SGc8qn6vITHk1S1mPevtekgasY5Y\r\n" -"iWQuM3h4YVlRH3HHEMAD1TnAexfXHHDFQGe+Bd1iAbz1/sH9H8l4StwX6egvTK3M\r\n" -"wXRwkKkvjKaEDA9ATbZx0mI8LGsxSuCqe9r9dyjmttd47J1p1Rulz3CLzaRcVIuS\r\n" -"RRQfaD8neM9c1S/iJ/amTVqJxA1KOdOS5780WhPfSArA+g4qAmSjelc3p4wWpha8\r\n" -"zhuYwjVuX6JHG0c=\r\n" +"FoAUtFrkpbPe0lL2udWmlQ/rPrzH/f8wDQYJKoZIhvcNAQEFBQADggEBAAFzC0rF\r\n" +"y6De8WMcdgQrEw3AhBHFjzqnxZw1ene4IBSC7lTw8rBSy3jOWQdPUWn+0y/pCeeF\r\n" +"kti6sevFdl1hLemGtd4q+T9TKEKGg3ND4ARfB5AUZZ9uEHq8WBkiwus5clGS17Qd\r\n" +"dS/TOisB59tQruLx1E1bPLtBKyqk4koC5WAULJwfpswGSyWJTpYwIpxcWE3D2tBu\r\n" +"UB6MZfXZFzWmWEOyKbeoXjXe8GBCGgHLywvYDsGQ36HSGtEsAvR2QaTLSxWYcfk1\r\n" +"fbDn4jSWkb4yZy1r01UEigFQtONieGwRFaUqEcFJHJvEEGVgh9keaVlOj2vrwf5r\r\n" +"4mN4lW7gLdenN6g=\r\n" "-----END CERTIFICATE-----\r\n"; const size_t mbedtls_test_srv_crt_rsa_len = sizeof( mbedtls_test_srv_crt_rsa ); +/* tests/data_files/server2.key */ const char mbedtls_test_srv_key_rsa[] = "-----BEGIN RSA PRIVATE KEY-----\r\n" "MIIEpAIBAAKCAQEAwU2j3efNHdEE10lyuJmsDnjkOjxKzzoTFtBa5M2jAIin7h5r\r\n" @@ -271,11 +273,12 @@ const char mbedtls_test_srv_key_rsa[] = "-----END RSA PRIVATE KEY-----\r\n"; const size_t mbedtls_test_srv_key_rsa_len = sizeof( mbedtls_test_srv_key_rsa ); +/* tests/data_files/cli-rsa-sha256.crt */ const char mbedtls_test_cli_crt_rsa[] = "-----BEGIN CERTIFICATE-----\r\n" -"MIIDhTCCAm2gAwIBAgIBBDANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJOTDER\r\n" +"MIIDPzCCAiegAwIBAgIBBDANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJOTDER\r\n" "MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" -"MTcwNTA1MTMwNzU5WhcNMjcwNTA2MTMwNzU5WjA8MQswCQYDVQQGEwJOTDERMA8G\r\n" +"MTEwMjEyMTQ0NDA2WhcNMjEwMjEyMTQ0NDA2WjA8MQswCQYDVQQGEwJOTDERMA8G\r\n" "A1UECgwIUG9sYXJTU0wxGjAYBgNVBAMMEVBvbGFyU1NMIENsaWVudCAyMIIBIjAN\r\n" "BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyHTEzLn5tXnpRdkUYLB9u5Pyax6f\r\n" "M60Nj4o8VmXl3ETZzGaFB9X4J7BKNdBjngpuG7fa8H6r7gwQk4ZJGDTzqCrSV/Uu\r\n" @@ -283,18 +286,18 @@ const char mbedtls_test_cli_crt_rsa[] = "MjDV0/YI0FZPRo7yX/k9Z5GIMC5Cst99++UMd//sMcB4j7/Cf8qtbCHWjdmLao5v\r\n" "4Jv4EFbMs44TFeY0BGbH7vk2DmqV9gmaBmf0ZXH4yqSxJeD+PIs1BGe64E92hfx/\r\n" "/DZrtenNLQNiTrM9AM+vdqBpVoNq0qjU51Bx5rU2BXcFbXvI5MT9TNUhXwIDAQAB\r\n" -"o4GSMIGPMB0GA1UdDgQWBBRxoQBzckAvVHZeM/xSj7zx3WtGITBjBgNVHSMEXDBa\r\n" -"gBS0WuSls97SUva51aaVD+s+vMf9/6E/pD0wOzELMAkGA1UEBhMCTkwxETAPBgNV\r\n" -"BAoMCFBvbGFyU1NMMRkwFwYDVQQDDBBQb2xhclNTTCBUZXN0IENBggEAMAkGA1Ud\r\n" -"EwQCMAAwDQYJKoZIhvcNAQELBQADggEBAC7yO786NvcHpK8UovKIG9cB32oSQQom\r\n" -"LoR0eHDRzdqEkoq7yGZufHFiRAAzbMqJfogRtxlrWAeB4y/jGaMBV25IbFOIcH2W\r\n" -"iCEaMMbG+VQLKNvuC63kmw/Zewc9ThM6Pa1Hcy0axT0faf1B/U01j0FIcw/6mTfK\r\n" -"D8w48OIwc1yr0JtutCVjig5DC0yznGMt32RyseOLcUe+lfq005v2PAiCozr5X8rE\r\n" -"ofGZpiM2NqRPePgYy+Vc75Zk28xkRQq1ncprgQb3S4vTsZdScpM9hLf+eMlrgqlj\r\n" -"c5PLSkXBeLE5+fedkyfTaLxxQlgCpuoOhKBm04/R1pWNzUHyqagjO9Q=\r\n" +"o00wSzAJBgNVHRMEAjAAMB0GA1UdDgQWBBRxoQBzckAvVHZeM/xSj7zx3WtGITAf\r\n" +"BgNVHSMEGDAWgBS0WuSls97SUva51aaVD+s+vMf9/zANBgkqhkiG9w0BAQsFAAOC\r\n" +"AQEAlHabem2Tu69VUN7EipwnQn1dIHdgvT5i+iQHpSxY1crPnBbAeSdAXwsVEqLQ\r\n" +"gOOIAQD5VIITNuoGgo4i+4OpNh9u7ZkpRHla+/swsfrFWRRbBNP5Bcu74AGLstwU\r\n" +"zM8gIkBiyfM1Q1qDQISV9trlCG6O8vh8dp/rbI3rfzo99BOHXgFCrzXjCuW4vDsF\r\n" +"r+Dao26bX3sJ6UnEWg1H3o2x6PpUcvQ36h71/bz4TEbbUUEpe02V4QWuL+wrhHJL\r\n" +"U7o3SVE3Og7jPF8sat0a50YUWhwEFI256m02KAXLg89ueUyYKEr6rNwhcvXJpvU9\r\n" +"giIVvd0Sbjjnn7NC4VDbcXV8vw==\r\n" "-----END CERTIFICATE-----\r\n"; const size_t mbedtls_test_cli_crt_rsa_len = sizeof( mbedtls_test_cli_crt_rsa ); +/* tests/data_files/cli-rsa.key */ const char mbedtls_test_cli_key_rsa[] = "-----BEGIN RSA PRIVATE KEY-----\r\n" "MIIEpAIBAAKCAQEAyHTEzLn5tXnpRdkUYLB9u5Pyax6fM60Nj4o8VmXl3ETZzGaF\r\n" diff --git a/thirdparty/mbedtls/library/chacha20.c b/thirdparty/mbedtls/library/chacha20.c index d14a51e044..0757163e2f 100644 --- a/thirdparty/mbedtls/library/chacha20.c +++ b/thirdparty/mbedtls/library/chacha20.c @@ -53,6 +53,12 @@ #define inline __inline #endif +/* Parameter validation macros */ +#define CHACHA20_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA ) +#define CHACHA20_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + #define BYTES_TO_U32_LE( data, offset ) \ ( (uint32_t) data[offset] \ | (uint32_t) ( (uint32_t) data[( offset ) + 1] << 8 ) \ @@ -181,14 +187,13 @@ static void chacha20_block( const uint32_t initial_state[16], void mbedtls_chacha20_init( mbedtls_chacha20_context *ctx ) { - if( ctx != NULL ) - { - mbedtls_platform_zeroize( ctx->state, sizeof( ctx->state ) ); - mbedtls_platform_zeroize( ctx->keystream8, sizeof( ctx->keystream8 ) ); + CHACHA20_VALIDATE( ctx != NULL ); - /* Initially, there's no keystream bytes available */ - ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES; - } + mbedtls_platform_zeroize( ctx->state, sizeof( ctx->state ) ); + mbedtls_platform_zeroize( ctx->keystream8, sizeof( ctx->keystream8 ) ); + + /* Initially, there's no keystream bytes available */ + ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES; } void mbedtls_chacha20_free( mbedtls_chacha20_context *ctx ) @@ -202,10 +207,8 @@ void mbedtls_chacha20_free( mbedtls_chacha20_context *ctx ) int mbedtls_chacha20_setkey( mbedtls_chacha20_context *ctx, const unsigned char key[32] ) { - if( ( ctx == NULL ) || ( key == NULL ) ) - { - return( MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA ); - } + CHACHA20_VALIDATE_RET( ctx != NULL ); + CHACHA20_VALIDATE_RET( key != NULL ); /* ChaCha20 constants - the string "expand 32-byte k" */ ctx->state[0] = 0x61707865; @@ -230,10 +233,8 @@ int mbedtls_chacha20_starts( mbedtls_chacha20_context* ctx, const unsigned char nonce[12], uint32_t counter ) { - if( ( ctx == NULL ) || ( nonce == NULL ) ) - { - return( MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA ); - } + CHACHA20_VALIDATE_RET( ctx != NULL ); + CHACHA20_VALIDATE_RET( nonce != NULL ); /* Counter */ ctx->state[12] = counter; @@ -259,15 +260,9 @@ int mbedtls_chacha20_update( mbedtls_chacha20_context *ctx, size_t offset = 0U; size_t i; - if( ctx == NULL ) - { - return( MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA ); - } - else if( ( size > 0U ) && ( ( input == NULL ) || ( output == NULL ) ) ) - { - /* input and output pointers are allowed to be NULL only if size == 0 */ - return( MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA ); - } + CHACHA20_VALIDATE_RET( ctx != NULL ); + CHACHA20_VALIDATE_RET( size == 0 || input != NULL ); + CHACHA20_VALIDATE_RET( size == 0 || output != NULL ); /* Use leftover keystream bytes, if available */ while( size > 0U && ctx->keystream_bytes_used < CHACHA20_BLOCK_SIZE_BYTES ) @@ -332,6 +327,11 @@ int mbedtls_chacha20_crypt( const unsigned char key[32], mbedtls_chacha20_context ctx; int ret; + CHACHA20_VALIDATE_RET( key != NULL ); + CHACHA20_VALIDATE_RET( nonce != NULL ); + CHACHA20_VALIDATE_RET( data_len == 0 || input != NULL ); + CHACHA20_VALIDATE_RET( data_len == 0 || output != NULL ); + mbedtls_chacha20_init( &ctx ); ret = mbedtls_chacha20_setkey( &ctx, key ); diff --git a/thirdparty/mbedtls/library/chachapoly.c b/thirdparty/mbedtls/library/chachapoly.c index 860f877653..dc643dd618 100644 --- a/thirdparty/mbedtls/library/chachapoly.c +++ b/thirdparty/mbedtls/library/chachapoly.c @@ -44,6 +44,12 @@ #if !defined(MBEDTLS_CHACHAPOLY_ALT) +/* Parameter validation macros */ +#define CHACHAPOLY_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA ) +#define CHACHAPOLY_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + #define CHACHAPOLY_STATE_INIT ( 0 ) #define CHACHAPOLY_STATE_AAD ( 1 ) #define CHACHAPOLY_STATE_CIPHERTEXT ( 2 ) /* Encrypting or decrypting */ @@ -90,39 +96,35 @@ static int chachapoly_pad_ciphertext( mbedtls_chachapoly_context *ctx ) void mbedtls_chachapoly_init( mbedtls_chachapoly_context *ctx ) { - if( ctx != NULL ) - { - mbedtls_chacha20_init( &ctx->chacha20_ctx ); - mbedtls_poly1305_init( &ctx->poly1305_ctx ); - ctx->aad_len = 0U; - ctx->ciphertext_len = 0U; - ctx->state = CHACHAPOLY_STATE_INIT; - ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT; - } + CHACHAPOLY_VALIDATE( ctx != NULL ); + + mbedtls_chacha20_init( &ctx->chacha20_ctx ); + mbedtls_poly1305_init( &ctx->poly1305_ctx ); + ctx->aad_len = 0U; + ctx->ciphertext_len = 0U; + ctx->state = CHACHAPOLY_STATE_INIT; + ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT; } void mbedtls_chachapoly_free( mbedtls_chachapoly_context *ctx ) { - if( ctx != NULL ) - { - mbedtls_chacha20_free( &ctx->chacha20_ctx ); - mbedtls_poly1305_free( &ctx->poly1305_ctx ); - ctx->aad_len = 0U; - ctx->ciphertext_len = 0U; - ctx->state = CHACHAPOLY_STATE_INIT; - ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT; - } + if( ctx == NULL ) + return; + + mbedtls_chacha20_free( &ctx->chacha20_ctx ); + mbedtls_poly1305_free( &ctx->poly1305_ctx ); + ctx->aad_len = 0U; + ctx->ciphertext_len = 0U; + ctx->state = CHACHAPOLY_STATE_INIT; + ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT; } int mbedtls_chachapoly_setkey( mbedtls_chachapoly_context *ctx, const unsigned char key[32] ) { int ret; - - if( ( ctx == NULL ) || ( key == NULL ) ) - { - return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA ); - } + CHACHAPOLY_VALIDATE_RET( ctx != NULL ); + CHACHAPOLY_VALIDATE_RET( key != NULL ); ret = mbedtls_chacha20_setkey( &ctx->chacha20_ctx, key ); @@ -135,11 +137,8 @@ int mbedtls_chachapoly_starts( mbedtls_chachapoly_context *ctx, { int ret; unsigned char poly1305_key[64]; - - if( ( ctx == NULL ) || ( nonce == NULL ) ) - { - return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA ); - } + CHACHAPOLY_VALIDATE_RET( ctx != NULL ); + CHACHAPOLY_VALIDATE_RET( nonce != NULL ); /* Set counter = 0, will be update to 1 when generating Poly1305 key */ ret = mbedtls_chacha20_starts( &ctx->chacha20_ctx, nonce, 0U ); @@ -176,19 +175,11 @@ int mbedtls_chachapoly_update_aad( mbedtls_chachapoly_context *ctx, const unsigned char *aad, size_t aad_len ) { - if( ctx == NULL ) - { - return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA ); - } - else if( ( aad_len > 0U ) && ( aad == NULL ) ) - { - /* aad pointer is allowed to be NULL if aad_len == 0 */ - return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA ); - } - else if( ctx->state != CHACHAPOLY_STATE_AAD ) - { + CHACHAPOLY_VALIDATE_RET( ctx != NULL ); + CHACHAPOLY_VALIDATE_RET( aad_len == 0 || aad != NULL ); + + if( ctx->state != CHACHAPOLY_STATE_AAD ) return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE ); - } ctx->aad_len += aad_len; @@ -201,18 +192,12 @@ int mbedtls_chachapoly_update( mbedtls_chachapoly_context *ctx, unsigned char *output ) { int ret; + CHACHAPOLY_VALIDATE_RET( ctx != NULL ); + CHACHAPOLY_VALIDATE_RET( len == 0 || input != NULL ); + CHACHAPOLY_VALIDATE_RET( len == 0 || output != NULL ); - if( ctx == NULL ) - { - return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA ); - } - else if( ( len > 0U ) && ( ( input == NULL ) || ( output == NULL ) ) ) - { - /* input and output pointers are allowed to be NULL if len == 0 */ - return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA ); - } - else if( ( ctx->state != CHACHAPOLY_STATE_AAD ) && - ( ctx->state != CHACHAPOLY_STATE_CIPHERTEXT ) ) + if( ( ctx->state != CHACHAPOLY_STATE_AAD ) && + ( ctx->state != CHACHAPOLY_STATE_CIPHERTEXT ) ) { return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE ); } @@ -257,12 +242,10 @@ int mbedtls_chachapoly_finish( mbedtls_chachapoly_context *ctx, { int ret; unsigned char len_block[16]; + CHACHAPOLY_VALIDATE_RET( ctx != NULL ); + CHACHAPOLY_VALIDATE_RET( mac != NULL ); - if( ( ctx == NULL ) || ( mac == NULL ) ) - { - return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA ); - } - else if( ctx->state == CHACHAPOLY_STATE_INIT ) + if( ctx->state == CHACHAPOLY_STATE_INIT ) { return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE ); } @@ -350,6 +333,13 @@ int mbedtls_chachapoly_encrypt_and_tag( mbedtls_chachapoly_context *ctx, unsigned char *output, unsigned char tag[16] ) { + CHACHAPOLY_VALIDATE_RET( ctx != NULL ); + CHACHAPOLY_VALIDATE_RET( nonce != NULL ); + CHACHAPOLY_VALIDATE_RET( tag != NULL ); + CHACHAPOLY_VALIDATE_RET( aad_len == 0 || aad != NULL ); + CHACHAPOLY_VALIDATE_RET( length == 0 || input != NULL ); + CHACHAPOLY_VALIDATE_RET( length == 0 || output != NULL ); + return( chachapoly_crypt_and_tag( ctx, MBEDTLS_CHACHAPOLY_ENCRYPT, length, nonce, aad, aad_len, input, output, tag ) ); @@ -368,9 +358,12 @@ int mbedtls_chachapoly_auth_decrypt( mbedtls_chachapoly_context *ctx, unsigned char check_tag[16]; size_t i; int diff; - - if( tag == NULL ) - return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA ); + CHACHAPOLY_VALIDATE_RET( ctx != NULL ); + CHACHAPOLY_VALIDATE_RET( nonce != NULL ); + CHACHAPOLY_VALIDATE_RET( tag != NULL ); + CHACHAPOLY_VALIDATE_RET( aad_len == 0 || aad != NULL ); + CHACHAPOLY_VALIDATE_RET( length == 0 || input != NULL ); + CHACHAPOLY_VALIDATE_RET( length == 0 || output != NULL ); if( ( ret = chachapoly_crypt_and_tag( ctx, MBEDTLS_CHACHAPOLY_DECRYPT, length, nonce, diff --git a/thirdparty/mbedtls/library/cipher.c b/thirdparty/mbedtls/library/cipher.c index 7ae6c4ac5d..273997577b 100644 --- a/thirdparty/mbedtls/library/cipher.c +++ b/thirdparty/mbedtls/library/cipher.c @@ -65,6 +65,11 @@ #define mbedtls_free free #endif +#define CIPHER_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ) +#define CIPHER_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + #if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) /* Compare the contents of two buffers in constant time. * Returns 0 if the contents are bitwise identical, otherwise returns @@ -81,7 +86,7 @@ static int mbedtls_constant_time_memcmp( const void *v1, const void *v2, size_t for( diff = 0, i = 0; i < len; i++ ) diff |= p1[i] ^ p2[i]; - return (int)diff; + return( (int)diff ); } #endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ @@ -150,6 +155,7 @@ const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values( const mbedtls_ciph void mbedtls_cipher_init( mbedtls_cipher_context_t *ctx ) { + CIPHER_VALIDATE( ctx != NULL ); memset( ctx, 0, sizeof( mbedtls_cipher_context_t ) ); } @@ -175,7 +181,8 @@ void mbedtls_cipher_free( mbedtls_cipher_context_t *ctx ) int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx, const mbedtls_cipher_info_t *cipher_info ) { - if( NULL == cipher_info || NULL == ctx ) + CIPHER_VALIDATE_RET( ctx != NULL ); + if( cipher_info == NULL ) return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); memset( ctx, 0, sizeof( mbedtls_cipher_context_t ) ); @@ -199,10 +206,16 @@ int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx, const mbedtls_cipher_in return( 0 ); } -int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx, const unsigned char *key, - int key_bitlen, const mbedtls_operation_t operation ) +int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx, + const unsigned char *key, + int key_bitlen, + const mbedtls_operation_t operation ) { - if( NULL == ctx || NULL == ctx->cipher_info ) + CIPHER_VALIDATE_RET( ctx != NULL ); + CIPHER_VALIDATE_RET( key != NULL ); + CIPHER_VALIDATE_RET( operation == MBEDTLS_ENCRYPT || + operation == MBEDTLS_DECRYPT ); + if( ctx->cipher_info == NULL ) return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); if( ( ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_KEY_LEN ) == 0 && @@ -222,23 +235,26 @@ int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx, const unsigned char *k MBEDTLS_MODE_OFB == ctx->cipher_info->mode || MBEDTLS_MODE_CTR == ctx->cipher_info->mode ) { - return ctx->cipher_info->base->setkey_enc_func( ctx->cipher_ctx, key, - ctx->key_bitlen ); + return( ctx->cipher_info->base->setkey_enc_func( ctx->cipher_ctx, key, + ctx->key_bitlen ) ); } if( MBEDTLS_DECRYPT == operation ) - return ctx->cipher_info->base->setkey_dec_func( ctx->cipher_ctx, key, - ctx->key_bitlen ); + return( ctx->cipher_info->base->setkey_dec_func( ctx->cipher_ctx, key, + ctx->key_bitlen ) ); return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); } int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx, - const unsigned char *iv, size_t iv_len ) + const unsigned char *iv, + size_t iv_len ) { size_t actual_iv_size; - if( NULL == ctx || NULL == ctx->cipher_info || NULL == iv ) + CIPHER_VALIDATE_RET( ctx != NULL ); + CIPHER_VALIDATE_RET( iv_len == 0 || iv != NULL ); + if( ctx->cipher_info == NULL ) return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); /* avoid buffer overflow in ctx->iv */ @@ -268,15 +284,19 @@ int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx, } #endif - memcpy( ctx->iv, iv, actual_iv_size ); - ctx->iv_size = actual_iv_size; + if ( actual_iv_size != 0 ) + { + memcpy( ctx->iv, iv, actual_iv_size ); + ctx->iv_size = actual_iv_size; + } return( 0 ); } int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx ) { - if( NULL == ctx || NULL == ctx->cipher_info ) + CIPHER_VALIDATE_RET( ctx != NULL ); + if( ctx->cipher_info == NULL ) return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); ctx->unprocessed_len = 0; @@ -288,14 +308,16 @@ int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx ) int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx, const unsigned char *ad, size_t ad_len ) { - if( NULL == ctx || NULL == ctx->cipher_info ) + CIPHER_VALIDATE_RET( ctx != NULL ); + CIPHER_VALIDATE_RET( ad_len == 0 || ad != NULL ); + if( ctx->cipher_info == NULL ) return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); #if defined(MBEDTLS_GCM_C) if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) { - return mbedtls_gcm_starts( (mbedtls_gcm_context *) ctx->cipher_ctx, ctx->operation, - ctx->iv, ctx->iv_size, ad, ad_len ); + return( mbedtls_gcm_starts( (mbedtls_gcm_context *) ctx->cipher_ctx, ctx->operation, + ctx->iv, ctx->iv_size, ad, ad_len ) ); } #endif @@ -315,8 +337,8 @@ int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx, if ( result != 0 ) return( result ); - return mbedtls_chachapoly_update_aad( (mbedtls_chachapoly_context*) ctx->cipher_ctx, - ad, ad_len ); + return( mbedtls_chachapoly_update_aad( (mbedtls_chachapoly_context*) ctx->cipher_ctx, + ad, ad_len ) ); } #endif @@ -328,12 +350,14 @@ int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *i size_t ilen, unsigned char *output, size_t *olen ) { int ret; - size_t block_size = 0; + size_t block_size; - if( NULL == ctx || NULL == ctx->cipher_info || NULL == olen ) - { + CIPHER_VALIDATE_RET( ctx != NULL ); + CIPHER_VALIDATE_RET( ilen == 0 || input != NULL ); + CIPHER_VALIDATE_RET( output != NULL ); + CIPHER_VALIDATE_RET( olen != NULL ); + if( ctx->cipher_info == NULL ) return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - } *olen = 0; block_size = mbedtls_cipher_get_block_size( ctx ); @@ -358,8 +382,8 @@ int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *i if( ctx->cipher_info->mode == MBEDTLS_MODE_GCM ) { *olen = ilen; - return mbedtls_gcm_update( (mbedtls_gcm_context *) ctx->cipher_ctx, ilen, input, - output ); + return( mbedtls_gcm_update( (mbedtls_gcm_context *) ctx->cipher_ctx, ilen, input, + output ) ); } #endif @@ -367,14 +391,14 @@ int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *i if ( ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20_POLY1305 ) { *olen = ilen; - return mbedtls_chachapoly_update( (mbedtls_chachapoly_context*) ctx->cipher_ctx, - ilen, input, output ); + return( mbedtls_chachapoly_update( (mbedtls_chachapoly_context*) ctx->cipher_ctx, + ilen, input, output ) ); } #endif if ( 0 == block_size ) { - return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT; + return( MBEDTLS_ERR_CIPHER_INVALID_CONTEXT ); } if( input == output && @@ -437,7 +461,7 @@ int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *i { if( 0 == block_size ) { - return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT; + return( MBEDTLS_ERR_CIPHER_INVALID_CONTEXT ); } /* Encryption: only cache partial blocks @@ -738,7 +762,10 @@ static int get_no_padding( unsigned char *input, size_t input_len, int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx, unsigned char *output, size_t *olen ) { - if( NULL == ctx || NULL == ctx->cipher_info || NULL == olen ) + CIPHER_VALIDATE_RET( ctx != NULL ); + CIPHER_VALIDATE_RET( output != NULL ); + CIPHER_VALIDATE_RET( olen != NULL ); + if( ctx->cipher_info == NULL ) return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); *olen = 0; @@ -808,8 +835,8 @@ int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx, /* Set output size for decryption */ if( MBEDTLS_DECRYPT == ctx->operation ) - return ctx->get_padding( output, mbedtls_cipher_get_block_size( ctx ), - olen ); + return( ctx->get_padding( output, mbedtls_cipher_get_block_size( ctx ), + olen ) ); /* Set output size for encryption */ *olen = mbedtls_cipher_get_block_size( ctx ); @@ -823,10 +850,12 @@ int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx, } #if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) -int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx, mbedtls_cipher_padding_t mode ) +int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx, + mbedtls_cipher_padding_t mode ) { - if( NULL == ctx || - MBEDTLS_MODE_CBC != ctx->cipher_info->mode ) + CIPHER_VALIDATE_RET( ctx != NULL ); + + if( NULL == ctx->cipher_info || MBEDTLS_MODE_CBC != ctx->cipher_info->mode ) { return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); } @@ -874,7 +903,9 @@ int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx, mbedtls_ciph int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx, unsigned char *tag, size_t tag_len ) { - if( NULL == ctx || NULL == ctx->cipher_info || NULL == tag ) + CIPHER_VALIDATE_RET( ctx != NULL ); + CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL ); + if( ctx->cipher_info == NULL ) return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); if( MBEDTLS_ENCRYPT != ctx->operation ) @@ -882,7 +913,8 @@ int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx, #if defined(MBEDTLS_GCM_C) if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) - return mbedtls_gcm_finish( (mbedtls_gcm_context *) ctx->cipher_ctx, tag, tag_len ); + return( mbedtls_gcm_finish( (mbedtls_gcm_context *) ctx->cipher_ctx, + tag, tag_len ) ); #endif #if defined(MBEDTLS_CHACHAPOLY_C) @@ -892,8 +924,8 @@ int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx, if ( tag_len != 16U ) return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - return mbedtls_chachapoly_finish( (mbedtls_chachapoly_context*) ctx->cipher_ctx, - tag ); + return( mbedtls_chachapoly_finish( (mbedtls_chachapoly_context*) ctx->cipher_ctx, + tag ) ); } #endif @@ -906,8 +938,12 @@ int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx, unsigned char check_tag[16]; int ret; - if( NULL == ctx || NULL == ctx->cipher_info || - MBEDTLS_DECRYPT != ctx->operation ) + CIPHER_VALIDATE_RET( ctx != NULL ); + CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL ); + if( ctx->cipher_info == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if( MBEDTLS_DECRYPT != ctx->operation ) { return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); } @@ -969,6 +1005,12 @@ int mbedtls_cipher_crypt( mbedtls_cipher_context_t *ctx, int ret; size_t finish_olen; + CIPHER_VALIDATE_RET( ctx != NULL ); + CIPHER_VALIDATE_RET( iv_len == 0 || iv != NULL ); + CIPHER_VALIDATE_RET( ilen == 0 || input != NULL ); + CIPHER_VALIDATE_RET( output != NULL ); + CIPHER_VALIDATE_RET( olen != NULL ); + if( ( ret = mbedtls_cipher_set_iv( ctx, iv, iv_len ) ) != 0 ) return( ret ); @@ -997,6 +1039,14 @@ int mbedtls_cipher_auth_encrypt( mbedtls_cipher_context_t *ctx, unsigned char *output, size_t *olen, unsigned char *tag, size_t tag_len ) { + CIPHER_VALIDATE_RET( ctx != NULL ); + CIPHER_VALIDATE_RET( iv != NULL ); + CIPHER_VALIDATE_RET( ad_len == 0 || ad != NULL ); + CIPHER_VALIDATE_RET( ilen == 0 || input != NULL ); + CIPHER_VALIDATE_RET( output != NULL ); + CIPHER_VALIDATE_RET( olen != NULL ); + CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL ); + #if defined(MBEDTLS_GCM_C) if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) { @@ -1044,6 +1094,14 @@ int mbedtls_cipher_auth_decrypt( mbedtls_cipher_context_t *ctx, unsigned char *output, size_t *olen, const unsigned char *tag, size_t tag_len ) { + CIPHER_VALIDATE_RET( ctx != NULL ); + CIPHER_VALIDATE_RET( iv != NULL ); + CIPHER_VALIDATE_RET( ad_len == 0 || ad != NULL ); + CIPHER_VALIDATE_RET( ilen == 0 || input != NULL ); + CIPHER_VALIDATE_RET( output != NULL ); + CIPHER_VALIDATE_RET( olen != NULL ); + CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL ); + #if defined(MBEDTLS_GCM_C) if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) { diff --git a/thirdparty/mbedtls/library/cipher_wrap.c b/thirdparty/mbedtls/library/cipher_wrap.c index 893490acc8..6dd8c5d3a9 100644 --- a/thirdparty/mbedtls/library/cipher_wrap.c +++ b/thirdparty/mbedtls/library/cipher_wrap.c @@ -258,7 +258,7 @@ static const mbedtls_cipher_info_t aes_128_ecb_info = { MBEDTLS_MODE_ECB, 128, "AES-128-ECB", - 16, + 0, 0, 16, &aes_info @@ -269,7 +269,7 @@ static const mbedtls_cipher_info_t aes_192_ecb_info = { MBEDTLS_MODE_ECB, 192, "AES-192-ECB", - 16, + 0, 0, 16, &aes_info @@ -280,7 +280,7 @@ static const mbedtls_cipher_info_t aes_256_ecb_info = { MBEDTLS_MODE_ECB, 256, "AES-256-ECB", - 16, + 0, 0, 16, &aes_info diff --git a/thirdparty/mbedtls/library/ctr_drbg.c b/thirdparty/mbedtls/library/ctr_drbg.c index d0e5ba862d..fb121575bb 100644 --- a/thirdparty/mbedtls/library/ctr_drbg.c +++ b/thirdparty/mbedtls/library/ctr_drbg.c @@ -66,6 +66,18 @@ void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx ) * Non-public function wrapped by mbedtls_ctr_drbg_seed(). Necessary to allow * NIST tests to succeed (which require known length fixed entropy) */ +/* CTR_DRBG_Instantiate with derivation function (SP 800-90A §10.2.1.3.2) + * mbedtls_ctr_drbg_seed_entropy_len(ctx, f_entropy, p_entropy, + * custom, len, entropy_len) + * implements + * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string, + * security_strength) -> initial_working_state + * with inputs + * custom[:len] = nonce || personalization_string + * where entropy_input comes from f_entropy for entropy_len bytes + * and with outputs + * ctx = initial_working_state + */ int mbedtls_ctr_drbg_seed_entropy_len( mbedtls_ctr_drbg_context *ctx, int (*f_entropy)(void *, unsigned char *, size_t), @@ -256,6 +268,14 @@ exit: return( ret ); } +/* CTR_DRBG_Update (SP 800-90A §10.2.1.2) + * ctr_drbg_update_internal(ctx, provided_data) + * implements + * CTR_DRBG_Update(provided_data, Key, V) + * with inputs and outputs + * ctx->aes_ctx = Key + * ctx->counter = V + */ static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx, const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] ) { @@ -279,9 +299,7 @@ static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx, * Crypt counter block */ if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, p ) ) != 0 ) - { - return( ret ); - } + goto exit; p += MBEDTLS_CTR_DRBG_BLOCKSIZE; } @@ -293,31 +311,71 @@ static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx, * Update key and counter */ if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 ) - { - return( ret ); - } + goto exit; memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE, MBEDTLS_CTR_DRBG_BLOCKSIZE ); - return( 0 ); +exit: + mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); + return( ret ); } -void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx, - const unsigned char *additional, size_t add_len ) +/* CTR_DRBG_Instantiate with derivation function (SP 800-90A §10.2.1.3.2) + * mbedtls_ctr_drbg_update(ctx, additional, add_len) + * implements + * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string, + * security_strength) -> initial_working_state + * with inputs + * ctx->counter = all-bits-0 + * ctx->aes_ctx = context from all-bits-0 key + * additional[:add_len] = entropy_input || nonce || personalization_string + * and with outputs + * ctx = initial_working_state + */ +int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx, + const unsigned char *additional, + size_t add_len ) { unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN]; + int ret; - if( add_len > 0 ) - { - /* MAX_INPUT would be more logical here, but we have to match - * block_cipher_df()'s limits since we can't propagate errors */ - if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ) - add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT; + if( add_len == 0 ) + return( 0 ); - block_cipher_df( add_input, additional, add_len ); - ctr_drbg_update_internal( ctx, add_input ); - } + if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 ) + goto exit; + if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 ) + goto exit; + +exit: + mbedtls_platform_zeroize( add_input, sizeof( add_input ) ); + return( ret ); } +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx, + const unsigned char *additional, + size_t add_len ) +{ + /* MAX_INPUT would be more logical here, but we have to match + * block_cipher_df()'s limits since we can't propagate errors */ + if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ) + add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT; + (void) mbedtls_ctr_drbg_update_ret( ctx, additional, add_len ); +} +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +/* CTR_DRBG_Reseed with derivation function (SP 800-90A §10.2.1.4.2) + * mbedtls_ctr_drbg_reseed(ctx, additional, len) + * implements + * CTR_DRBG_Reseed(working_state, entropy_input, additional_input) + * -> new_working_state + * with inputs + * ctx contains working_state + * additional[:len] = additional_input + * and entropy_input comes from calling ctx->f_entropy + * and with output + * ctx contains new_working_state + */ int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx, const unsigned char *additional, size_t len ) { @@ -355,22 +413,39 @@ int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx, * Reduce to 384 bits */ if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 ) - { - return( ret ); - } + goto exit; /* * Update state */ if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 ) - { - return( ret ); - } + goto exit; ctx->reseed_counter = 1; - return( 0 ); +exit: + mbedtls_platform_zeroize( seed, sizeof( seed ) ); + return( ret ); } +/* CTR_DRBG_Generate with derivation function (SP 800-90A §10.2.1.5.2) + * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len) + * implements + * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len]) + * -> working_state_after_reseed + * if required, then + * CTR_DRBG_Generate(working_state_after_reseed, + * requested_number_of_bits, additional_input) + * -> status, returned_bits, new_working_state + * with inputs + * ctx contains working_state + * requested_number_of_bits = 8 * output_len + * additional[:add_len] = additional_input + * and entropy_input comes from calling ctx->f_entropy + * and with outputs + * status = SUCCESS (this function does the reseed internally) + * returned_bits = output[:output_len] + * ctx contains new_working_state + */ int mbedtls_ctr_drbg_random_with_add( void *p_rng, unsigned char *output, size_t output_len, const unsigned char *additional, size_t add_len ) @@ -404,13 +479,9 @@ int mbedtls_ctr_drbg_random_with_add( void *p_rng, if( add_len > 0 ) { if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 ) - { - return( ret ); - } + goto exit; if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 ) - { - return( ret ); - } + goto exit; } while( output_len > 0 ) @@ -426,9 +497,7 @@ int mbedtls_ctr_drbg_random_with_add( void *p_rng, * Crypt counter block */ if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, tmp ) ) != 0 ) - { - return( ret ); - } + goto exit; use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? MBEDTLS_CTR_DRBG_BLOCKSIZE : output_len; @@ -441,12 +510,13 @@ int mbedtls_ctr_drbg_random_with_add( void *p_rng, } if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 ) - { - return( ret ); - } + goto exit; ctx->reseed_counter++; +exit: + mbedtls_platform_zeroize( add_input, sizeof( add_input ) ); + mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); return( 0 ); } @@ -498,35 +568,36 @@ exit: int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path ) { int ret = 0; - FILE *f; + FILE *f = NULL; size_t n; unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ]; + unsigned char c; if( ( f = fopen( path, "rb" ) ) == NULL ) return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR ); - fseek( f, 0, SEEK_END ); - n = (size_t) ftell( f ); - fseek( f, 0, SEEK_SET ); - - if( n > MBEDTLS_CTR_DRBG_MAX_INPUT ) + n = fread( buf, 1, sizeof( buf ), f ); + if( fread( &c, 1, 1, f ) != 0 ) { - fclose( f ); - return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); + ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG; + goto exit; } - - if( fread( buf, 1, n, f ) != n ) + if( n == 0 || ferror( f ) ) + { ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; - else - mbedtls_ctr_drbg_update( ctx, buf, n ); - + goto exit; + } fclose( f ); + f = NULL; - mbedtls_platform_zeroize( buf, sizeof( buf ) ); + ret = mbedtls_ctr_drbg_update_ret( ctx, buf, n ); +exit: + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + if( f != NULL ) + fclose( f ); if( ret != 0 ) return( ret ); - return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) ); } #endif /* MBEDTLS_FS_IO */ diff --git a/thirdparty/mbedtls/library/debug.c b/thirdparty/mbedtls/library/debug.c index db3924ac54..824cd0236e 100644 --- a/thirdparty/mbedtls/library/debug.c +++ b/thirdparty/mbedtls/library/debug.c @@ -365,4 +365,54 @@ void mbedtls_debug_print_crt( const mbedtls_ssl_context *ssl, int level, } #endif /* MBEDTLS_X509_CRT_PARSE_C */ +#if defined(MBEDTLS_ECDH_C) +static void mbedtls_debug_printf_ecdh_internal( const mbedtls_ssl_context *ssl, + int level, const char *file, + int line, + const mbedtls_ecdh_context *ecdh, + mbedtls_debug_ecdh_attr attr ) +{ +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + const mbedtls_ecdh_context* ctx = ecdh; +#else + const mbedtls_ecdh_context_mbed* ctx = &ecdh->ctx.mbed_ecdh; +#endif + + switch( attr ) + { + case MBEDTLS_DEBUG_ECDH_Q: + mbedtls_debug_print_ecp( ssl, level, file, line, "ECDH: Q", + &ctx->Q ); + break; + case MBEDTLS_DEBUG_ECDH_QP: + mbedtls_debug_print_ecp( ssl, level, file, line, "ECDH: Qp", + &ctx->Qp ); + break; + case MBEDTLS_DEBUG_ECDH_Z: + mbedtls_debug_print_mpi( ssl, level, file, line, "ECDH: z", + &ctx->z ); + break; + default: + break; + } +} + +void mbedtls_debug_printf_ecdh( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const mbedtls_ecdh_context *ecdh, + mbedtls_debug_ecdh_attr attr ) +{ +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + mbedtls_debug_printf_ecdh_internal( ssl, level, file, line, ecdh, attr ); +#else + switch( ecdh->var ) + { + default: + mbedtls_debug_printf_ecdh_internal( ssl, level, file, line, ecdh, + attr ); + } +#endif +} +#endif /* MBEDTLS_ECDH_C */ + #endif /* MBEDTLS_DEBUG_C */ diff --git a/thirdparty/mbedtls/library/dhm.c b/thirdparty/mbedtls/library/dhm.c index 82cbb0ce88..fb6937e854 100644 --- a/thirdparty/mbedtls/library/dhm.c +++ b/thirdparty/mbedtls/library/dhm.c @@ -60,6 +60,11 @@ #if !defined(MBEDTLS_DHM_ALT) +#define DHM_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_DHM_BAD_INPUT_DATA ) +#define DHM_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + /* * helper to validate the mbedtls_mpi size and import it */ @@ -121,6 +126,7 @@ cleanup: void mbedtls_dhm_init( mbedtls_dhm_context *ctx ) { + DHM_VALIDATE( ctx != NULL ); memset( ctx, 0, sizeof( mbedtls_dhm_context ) ); } @@ -132,6 +138,9 @@ int mbedtls_dhm_read_params( mbedtls_dhm_context *ctx, const unsigned char *end ) { int ret; + DHM_VALIDATE_RET( ctx != NULL ); + DHM_VALIDATE_RET( p != NULL && *p != NULL ); + DHM_VALIDATE_RET( end != NULL ); if( ( ret = dhm_read_bignum( &ctx->P, p, end ) ) != 0 || ( ret = dhm_read_bignum( &ctx->G, p, end ) ) != 0 || @@ -157,6 +166,10 @@ int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size, int ret, count = 0; size_t n1, n2, n3; unsigned char *p; + DHM_VALIDATE_RET( ctx != NULL ); + DHM_VALIDATE_RET( output != NULL ); + DHM_VALIDATE_RET( olen != NULL ); + DHM_VALIDATE_RET( f_rng != NULL ); if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 ) return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); @@ -227,9 +240,9 @@ int mbedtls_dhm_set_group( mbedtls_dhm_context *ctx, const mbedtls_mpi *G ) { int ret; - - if( ctx == NULL || P == NULL || G == NULL ) - return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); + DHM_VALIDATE_RET( ctx != NULL ); + DHM_VALIDATE_RET( P != NULL ); + DHM_VALIDATE_RET( G != NULL ); if( ( ret = mbedtls_mpi_copy( &ctx->P, P ) ) != 0 || ( ret = mbedtls_mpi_copy( &ctx->G, G ) ) != 0 ) @@ -248,8 +261,10 @@ int mbedtls_dhm_read_public( mbedtls_dhm_context *ctx, const unsigned char *input, size_t ilen ) { int ret; + DHM_VALIDATE_RET( ctx != NULL ); + DHM_VALIDATE_RET( input != NULL ); - if( ctx == NULL || ilen < 1 || ilen > ctx->len ) + if( ilen < 1 || ilen > ctx->len ) return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); if( ( ret = mbedtls_mpi_read_binary( &ctx->GY, input, ilen ) ) != 0 ) @@ -267,8 +282,11 @@ int mbedtls_dhm_make_public( mbedtls_dhm_context *ctx, int x_size, void *p_rng ) { int ret, count = 0; + DHM_VALIDATE_RET( ctx != NULL ); + DHM_VALIDATE_RET( output != NULL ); + DHM_VALIDATE_RET( f_rng != NULL ); - if( ctx == NULL || olen < 1 || olen > ctx->len ) + if( olen < 1 || olen > ctx->len ) return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 ) @@ -380,8 +398,11 @@ int mbedtls_dhm_calc_secret( mbedtls_dhm_context *ctx, { int ret; mbedtls_mpi GYb; + DHM_VALIDATE_RET( ctx != NULL ); + DHM_VALIDATE_RET( output != NULL ); + DHM_VALIDATE_RET( olen != NULL ); - if( ctx == NULL || output_size < ctx->len ) + if( output_size < ctx->len ) return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 ) @@ -428,11 +449,19 @@ cleanup: */ void mbedtls_dhm_free( mbedtls_dhm_context *ctx ) { - mbedtls_mpi_free( &ctx->pX ); mbedtls_mpi_free( &ctx->Vf ); - mbedtls_mpi_free( &ctx->Vi ); mbedtls_mpi_free( &ctx->RP ); - mbedtls_mpi_free( &ctx->K ); mbedtls_mpi_free( &ctx->GY ); - mbedtls_mpi_free( &ctx->GX ); mbedtls_mpi_free( &ctx->X ); - mbedtls_mpi_free( &ctx->G ); mbedtls_mpi_free( &ctx->P ); + if( ctx == NULL ) + return; + + mbedtls_mpi_free( &ctx->pX ); + mbedtls_mpi_free( &ctx->Vf ); + mbedtls_mpi_free( &ctx->Vi ); + mbedtls_mpi_free( &ctx->RP ); + mbedtls_mpi_free( &ctx->K ); + mbedtls_mpi_free( &ctx->GY ); + mbedtls_mpi_free( &ctx->GX ); + mbedtls_mpi_free( &ctx->X ); + mbedtls_mpi_free( &ctx->G ); + mbedtls_mpi_free( &ctx->P ); mbedtls_platform_zeroize( ctx, sizeof( mbedtls_dhm_context ) ); } @@ -449,7 +478,12 @@ int mbedtls_dhm_parse_dhm( mbedtls_dhm_context *dhm, const unsigned char *dhmin, unsigned char *p, *end; #if defined(MBEDTLS_PEM_PARSE_C) mbedtls_pem_context pem; +#endif /* MBEDTLS_PEM_PARSE_C */ + + DHM_VALIDATE_RET( dhm != NULL ); + DHM_VALIDATE_RET( dhmin != NULL ); +#if defined(MBEDTLS_PEM_PARSE_C) mbedtls_pem_init( &pem ); /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ @@ -596,6 +630,8 @@ int mbedtls_dhm_parse_dhmfile( mbedtls_dhm_context *dhm, const char *path ) int ret; size_t n; unsigned char *buf; + DHM_VALIDATE_RET( dhm != NULL ); + DHM_VALIDATE_RET( path != NULL ); if( ( ret = load_file( path, &buf, &n ) ) != 0 ) return( ret ); diff --git a/thirdparty/mbedtls/library/ecdh.c b/thirdparty/mbedtls/library/ecdh.c index 61380b6936..da95c60dad 100644 --- a/thirdparty/mbedtls/library/ecdh.c +++ b/thirdparty/mbedtls/library/ecdh.c @@ -35,41 +35,82 @@ #if defined(MBEDTLS_ECDH_C) #include "mbedtls/ecdh.h" +#include "mbedtls/platform_util.h" #include <string.h> +/* Parameter validation macros based on platform_util.h */ +#define ECDH_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA ) +#define ECDH_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) +typedef mbedtls_ecdh_context mbedtls_ecdh_context_mbed; +#endif + #if !defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT) /* - * Generate public key: simple wrapper around mbedtls_ecp_gen_keypair + * Generate public key (restartable version) + * + * Note: this internal function relies on its caller preserving the value of + * the output parameter 'd' across continuation calls. This would not be + * acceptable for a public function but is OK here as we control call sites. + */ +static int ecdh_gen_public_restartable( mbedtls_ecp_group *grp, + mbedtls_mpi *d, mbedtls_ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_ecp_restart_ctx *rs_ctx ) +{ + int ret; + + /* If multiplication is in progress, we already generated a privkey */ +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx == NULL || rs_ctx->rsm == NULL ) +#endif + MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, d, f_rng, p_rng ) ); + + MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, Q, d, &grp->G, + f_rng, p_rng, rs_ctx ) ); + +cleanup: + return( ret ); +} + +/* + * Generate public key */ int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { - return mbedtls_ecp_gen_keypair( grp, d, Q, f_rng, p_rng ); + ECDH_VALIDATE_RET( grp != NULL ); + ECDH_VALIDATE_RET( d != NULL ); + ECDH_VALIDATE_RET( Q != NULL ); + ECDH_VALIDATE_RET( f_rng != NULL ); + return( ecdh_gen_public_restartable( grp, d, Q, f_rng, p_rng, NULL ) ); } -#endif /* MBEDTLS_ECDH_GEN_PUBLIC_ALT */ +#endif /* !MBEDTLS_ECDH_GEN_PUBLIC_ALT */ #if !defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT) /* * Compute shared secret (SEC1 3.3.1) */ -int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z, +static int ecdh_compute_shared_restartable( mbedtls_ecp_group *grp, + mbedtls_mpi *z, const mbedtls_ecp_point *Q, const mbedtls_mpi *d, int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) + void *p_rng, + mbedtls_ecp_restart_ctx *rs_ctx ) { int ret; mbedtls_ecp_point P; mbedtls_ecp_point_init( &P ); - /* - * Make sure Q is a valid pubkey before using it - */ - MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, Q ) ); - - MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, &P, d, Q, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, &P, d, Q, + f_rng, p_rng, rs_ctx ) ); if( mbedtls_ecp_is_zero( &P ) ) { @@ -84,65 +125,195 @@ cleanup: return( ret ); } -#endif /* MBEDTLS_ECDH_COMPUTE_SHARED_ALT */ + +/* + * Compute shared secret (SEC1 3.3.1) + */ +int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z, + const mbedtls_ecp_point *Q, const mbedtls_mpi *d, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + ECDH_VALIDATE_RET( grp != NULL ); + ECDH_VALIDATE_RET( Q != NULL ); + ECDH_VALIDATE_RET( d != NULL ); + ECDH_VALIDATE_RET( z != NULL ); + return( ecdh_compute_shared_restartable( grp, z, Q, d, + f_rng, p_rng, NULL ) ); +} +#endif /* !MBEDTLS_ECDH_COMPUTE_SHARED_ALT */ + +static void ecdh_init_internal( mbedtls_ecdh_context_mbed *ctx ) +{ + mbedtls_ecp_group_init( &ctx->grp ); + mbedtls_mpi_init( &ctx->d ); + mbedtls_ecp_point_init( &ctx->Q ); + mbedtls_ecp_point_init( &ctx->Qp ); + mbedtls_mpi_init( &ctx->z ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + mbedtls_ecp_restart_init( &ctx->rs ); +#endif +} /* * Initialize context */ void mbedtls_ecdh_init( mbedtls_ecdh_context *ctx ) { + ECDH_VALIDATE( ctx != NULL ); + +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + ecdh_init_internal( ctx ); + mbedtls_ecp_point_init( &ctx->Vi ); + mbedtls_ecp_point_init( &ctx->Vf ); + mbedtls_mpi_init( &ctx->_d ); +#else memset( ctx, 0, sizeof( mbedtls_ecdh_context ) ); + + ctx->var = MBEDTLS_ECDH_VARIANT_NONE; +#endif + ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED; +#if defined(MBEDTLS_ECP_RESTARTABLE) + ctx->restart_enabled = 0; +#endif +} + +static int ecdh_setup_internal( mbedtls_ecdh_context_mbed *ctx, + mbedtls_ecp_group_id grp_id ) +{ + int ret; + + ret = mbedtls_ecp_group_load( &ctx->grp, grp_id ); + if( ret != 0 ) + { + return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); + } + + return( 0 ); } /* - * Free context + * Setup context */ -void mbedtls_ecdh_free( mbedtls_ecdh_context *ctx ) +int mbedtls_ecdh_setup( mbedtls_ecdh_context *ctx, mbedtls_ecp_group_id grp_id ) { - if( ctx == NULL ) - return; + ECDH_VALIDATE_RET( ctx != NULL ); +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + return( ecdh_setup_internal( ctx, grp_id ) ); +#else + switch( grp_id ) + { + default: + ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED; + ctx->var = MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0; + ctx->grp_id = grp_id; + ecdh_init_internal( &ctx->ctx.mbed_ecdh ); + return( ecdh_setup_internal( &ctx->ctx.mbed_ecdh, grp_id ) ); + } +#endif +} + +static void ecdh_free_internal( mbedtls_ecdh_context_mbed *ctx ) +{ mbedtls_ecp_group_free( &ctx->grp ); + mbedtls_mpi_free( &ctx->d ); mbedtls_ecp_point_free( &ctx->Q ); mbedtls_ecp_point_free( &ctx->Qp ); - mbedtls_ecp_point_free( &ctx->Vi ); - mbedtls_ecp_point_free( &ctx->Vf ); - mbedtls_mpi_free( &ctx->d ); mbedtls_mpi_free( &ctx->z ); - mbedtls_mpi_free( &ctx->_d ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + mbedtls_ecp_restart_free( &ctx->rs ); +#endif } +#if defined(MBEDTLS_ECP_RESTARTABLE) /* - * Setup and write the ServerKeyExhange parameters (RFC 4492) - * struct { - * ECParameters curve_params; - * ECPoint public; - * } ServerECDHParams; + * Enable restartable operations for context */ -int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen, - unsigned char *buf, size_t blen, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) +void mbedtls_ecdh_enable_restart( mbedtls_ecdh_context *ctx ) +{ + ECDH_VALIDATE( ctx != NULL ); + + ctx->restart_enabled = 1; +} +#endif + +/* + * Free context + */ +void mbedtls_ecdh_free( mbedtls_ecdh_context *ctx ) +{ + if( ctx == NULL ) + return; + +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + mbedtls_ecp_point_free( &ctx->Vi ); + mbedtls_ecp_point_free( &ctx->Vf ); + mbedtls_mpi_free( &ctx->_d ); + ecdh_free_internal( ctx ); +#else + switch( ctx->var ) + { + case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: + ecdh_free_internal( &ctx->ctx.mbed_ecdh ); + break; + default: + break; + } + + ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED; + ctx->var = MBEDTLS_ECDH_VARIANT_NONE; + ctx->grp_id = MBEDTLS_ECP_DP_NONE; +#endif +} + +static int ecdh_make_params_internal( mbedtls_ecdh_context_mbed *ctx, + size_t *olen, int point_format, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, + unsigned char *, + size_t), + void *p_rng, + int restart_enabled ) { int ret; size_t grp_len, pt_len; +#if defined(MBEDTLS_ECP_RESTARTABLE) + mbedtls_ecp_restart_ctx *rs_ctx = NULL; +#endif - if( ctx == NULL || ctx->grp.pbits == 0 ) + if( ctx->grp.pbits == 0 ) return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng ) ) - != 0 ) +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( restart_enabled ) + rs_ctx = &ctx->rs; +#else + (void) restart_enabled; +#endif + + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( ( ret = ecdh_gen_public_restartable( &ctx->grp, &ctx->d, &ctx->Q, + f_rng, p_rng, rs_ctx ) ) != 0 ) return( ret ); +#else + if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q, + f_rng, p_rng ) ) != 0 ) + return( ret ); +#endif /* MBEDTLS_ECP_RESTARTABLE */ - if( ( ret = mbedtls_ecp_tls_write_group( &ctx->grp, &grp_len, buf, blen ) ) - != 0 ) + if( ( ret = mbedtls_ecp_tls_write_group( &ctx->grp, &grp_len, buf, + blen ) ) != 0 ) return( ret ); buf += grp_len; blen -= grp_len; - if( ( ret = mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, ctx->point_format, - &pt_len, buf, blen ) ) != 0 ) + if( ( ret = mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, point_format, + &pt_len, buf, blen ) ) != 0 ) return( ret ); *olen = grp_len + pt_len; @@ -150,6 +321,55 @@ int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen, } /* + * Setup and write the ServerKeyExhange parameters (RFC 4492) + * struct { + * ECParameters curve_params; + * ECPoint public; + * } ServerECDHParams; + */ +int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int restart_enabled = 0; + ECDH_VALIDATE_RET( ctx != NULL ); + ECDH_VALIDATE_RET( olen != NULL ); + ECDH_VALIDATE_RET( buf != NULL ); + ECDH_VALIDATE_RET( f_rng != NULL ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + restart_enabled = ctx->restart_enabled; +#else + (void) restart_enabled; +#endif + +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + return( ecdh_make_params_internal( ctx, olen, ctx->point_format, buf, blen, + f_rng, p_rng, restart_enabled ) ); +#else + switch( ctx->var ) + { + case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: + return( ecdh_make_params_internal( &ctx->ctx.mbed_ecdh, olen, + ctx->point_format, buf, blen, + f_rng, p_rng, + restart_enabled ) ); + default: + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } +#endif +} + +static int ecdh_read_params_internal( mbedtls_ecdh_context_mbed *ctx, + const unsigned char **buf, + const unsigned char *end ) +{ + return( mbedtls_ecp_tls_read_point( &ctx->grp, &ctx->Qp, buf, + end - *buf ) ); +} + +/* * Read the ServerKeyExhange parameters (RFC 4492) * struct { * ECParameters curve_params; @@ -157,31 +377,43 @@ int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen, * } ServerECDHParams; */ int mbedtls_ecdh_read_params( mbedtls_ecdh_context *ctx, - const unsigned char **buf, const unsigned char *end ) + const unsigned char **buf, + const unsigned char *end ) { int ret; - - if( ( ret = mbedtls_ecp_tls_read_group( &ctx->grp, buf, end - *buf ) ) != 0 ) + mbedtls_ecp_group_id grp_id; + ECDH_VALIDATE_RET( ctx != NULL ); + ECDH_VALIDATE_RET( buf != NULL ); + ECDH_VALIDATE_RET( *buf != NULL ); + ECDH_VALIDATE_RET( end != NULL ); + + if( ( ret = mbedtls_ecp_tls_read_group_id( &grp_id, buf, end - *buf ) ) + != 0 ) return( ret ); - if( ( ret = mbedtls_ecp_tls_read_point( &ctx->grp, &ctx->Qp, buf, end - *buf ) ) - != 0 ) + if( ( ret = mbedtls_ecdh_setup( ctx, grp_id ) ) != 0 ) return( ret ); - return( 0 ); +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + return( ecdh_read_params_internal( ctx, buf, end ) ); +#else + switch( ctx->var ) + { + case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: + return( ecdh_read_params_internal( &ctx->ctx.mbed_ecdh, + buf, end ) ); + default: + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } +#endif } -/* - * Get parameters from a keypair - */ -int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx, const mbedtls_ecp_keypair *key, - mbedtls_ecdh_side side ) +static int ecdh_get_params_internal( mbedtls_ecdh_context_mbed *ctx, + const mbedtls_ecp_keypair *key, + mbedtls_ecdh_side side ) { int ret; - if( ( ret = mbedtls_ecp_group_copy( &ctx->grp, &key->grp ) ) != 0 ) - return( ret ); - /* If it's not our key, just import the public part as Qp */ if( side == MBEDTLS_ECDH_THEIRS ) return( mbedtls_ecp_copy( &ctx->Qp, &key->Q ) ); @@ -198,39 +430,116 @@ int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx, const mbedtls_ecp_keypai } /* - * Setup and export the client public value + * Get parameters from a keypair */ -int mbedtls_ecdh_make_public( mbedtls_ecdh_context *ctx, size_t *olen, - unsigned char *buf, size_t blen, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) +int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx, + const mbedtls_ecp_keypair *key, + mbedtls_ecdh_side side ) { int ret; + ECDH_VALIDATE_RET( ctx != NULL ); + ECDH_VALIDATE_RET( key != NULL ); + ECDH_VALIDATE_RET( side == MBEDTLS_ECDH_OURS || + side == MBEDTLS_ECDH_THEIRS ); - if( ctx == NULL || ctx->grp.pbits == 0 ) + if( ( ret = mbedtls_ecdh_setup( ctx, key->grp.id ) ) != 0 ) + return( ret ); + +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + return( ecdh_get_params_internal( ctx, key, side ) ); +#else + switch( ctx->var ) + { + case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: + return( ecdh_get_params_internal( &ctx->ctx.mbed_ecdh, + key, side ) ); + default: + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } +#endif +} + +static int ecdh_make_public_internal( mbedtls_ecdh_context_mbed *ctx, + size_t *olen, int point_format, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, + unsigned char *, + size_t), + void *p_rng, + int restart_enabled ) +{ + int ret; +#if defined(MBEDTLS_ECP_RESTARTABLE) + mbedtls_ecp_restart_ctx *rs_ctx = NULL; +#endif + + if( ctx->grp.pbits == 0 ) return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng ) ) - != 0 ) +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( restart_enabled ) + rs_ctx = &ctx->rs; +#else + (void) restart_enabled; +#endif + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( ( ret = ecdh_gen_public_restartable( &ctx->grp, &ctx->d, &ctx->Q, + f_rng, p_rng, rs_ctx ) ) != 0 ) + return( ret ); +#else + if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q, + f_rng, p_rng ) ) != 0 ) return( ret ); +#endif /* MBEDTLS_ECP_RESTARTABLE */ - return mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, ctx->point_format, - olen, buf, blen ); + return mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, point_format, olen, + buf, blen ); } /* - * Parse and import the client's public value + * Setup and export the client public value */ -int mbedtls_ecdh_read_public( mbedtls_ecdh_context *ctx, - const unsigned char *buf, size_t blen ) +int mbedtls_ecdh_make_public( mbedtls_ecdh_context *ctx, size_t *olen, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int restart_enabled = 0; + ECDH_VALIDATE_RET( ctx != NULL ); + ECDH_VALIDATE_RET( olen != NULL ); + ECDH_VALIDATE_RET( buf != NULL ); + ECDH_VALIDATE_RET( f_rng != NULL ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + restart_enabled = ctx->restart_enabled; +#endif + +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + return( ecdh_make_public_internal( ctx, olen, ctx->point_format, buf, blen, + f_rng, p_rng, restart_enabled ) ); +#else + switch( ctx->var ) + { + case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: + return( ecdh_make_public_internal( &ctx->ctx.mbed_ecdh, olen, + ctx->point_format, buf, blen, + f_rng, p_rng, + restart_enabled ) ); + default: + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } +#endif +} + +static int ecdh_read_public_internal( mbedtls_ecdh_context_mbed *ctx, + const unsigned char *buf, size_t blen ) { int ret; const unsigned char *p = buf; - if( ctx == NULL ) - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - - if( ( ret = mbedtls_ecp_tls_read_point( &ctx->grp, &ctx->Qp, &p, blen ) ) != 0 ) + if( ( ret = mbedtls_ecp_tls_read_point( &ctx->grp, &ctx->Qp, &p, + blen ) ) != 0 ) return( ret ); if( (size_t)( p - buf ) != blen ) @@ -240,23 +549,66 @@ int mbedtls_ecdh_read_public( mbedtls_ecdh_context *ctx, } /* - * Derive and export the shared secret + * Parse and import the client's public value */ -int mbedtls_ecdh_calc_secret( mbedtls_ecdh_context *ctx, size_t *olen, - unsigned char *buf, size_t blen, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) +int mbedtls_ecdh_read_public( mbedtls_ecdh_context *ctx, + const unsigned char *buf, size_t blen ) +{ + ECDH_VALIDATE_RET( ctx != NULL ); + ECDH_VALIDATE_RET( buf != NULL ); + +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + return( ecdh_read_public_internal( ctx, buf, blen ) ); +#else + switch( ctx->var ) + { + case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: + return( ecdh_read_public_internal( &ctx->ctx.mbed_ecdh, + buf, blen ) ); + default: + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } +#endif +} + +static int ecdh_calc_secret_internal( mbedtls_ecdh_context_mbed *ctx, + size_t *olen, unsigned char *buf, + size_t blen, + int (*f_rng)(void *, + unsigned char *, + size_t), + void *p_rng, + int restart_enabled ) { int ret; +#if defined(MBEDTLS_ECP_RESTARTABLE) + mbedtls_ecp_restart_ctx *rs_ctx = NULL; +#endif - if( ctx == NULL ) + if( ctx == NULL || ctx->grp.pbits == 0 ) return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - if( ( ret = mbedtls_ecdh_compute_shared( &ctx->grp, &ctx->z, &ctx->Qp, &ctx->d, - f_rng, p_rng ) ) != 0 ) +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( restart_enabled ) + rs_ctx = &ctx->rs; +#else + (void) restart_enabled; +#endif + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( ( ret = ecdh_compute_shared_restartable( &ctx->grp, &ctx->z, &ctx->Qp, + &ctx->d, f_rng, p_rng, + rs_ctx ) ) != 0 ) { return( ret ); } +#else + if( ( ret = mbedtls_ecdh_compute_shared( &ctx->grp, &ctx->z, &ctx->Qp, + &ctx->d, f_rng, p_rng ) ) != 0 ) + { + return( ret ); + } +#endif /* MBEDTLS_ECP_RESTARTABLE */ if( mbedtls_mpi_size( &ctx->z ) > blen ) return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); @@ -265,4 +617,37 @@ int mbedtls_ecdh_calc_secret( mbedtls_ecdh_context *ctx, size_t *olen, return mbedtls_mpi_write_binary( &ctx->z, buf, *olen ); } +/* + * Derive and export the shared secret + */ +int mbedtls_ecdh_calc_secret( mbedtls_ecdh_context *ctx, size_t *olen, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int restart_enabled = 0; + ECDH_VALIDATE_RET( ctx != NULL ); + ECDH_VALIDATE_RET( olen != NULL ); + ECDH_VALIDATE_RET( buf != NULL ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + restart_enabled = ctx->restart_enabled; +#endif + +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + return( ecdh_calc_secret_internal( ctx, olen, buf, blen, f_rng, p_rng, + restart_enabled ) ); +#else + switch( ctx->var ) + { + case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: + return( ecdh_calc_secret_internal( &ctx->ctx.mbed_ecdh, olen, buf, + blen, f_rng, p_rng, + restart_enabled ) ); + default: + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + } +#endif +} + #endif /* MBEDTLS_ECDH_C */ diff --git a/thirdparty/mbedtls/library/ecdsa.c b/thirdparty/mbedtls/library/ecdsa.c index 17a88bdd29..1204ef9949 100644 --- a/thirdparty/mbedtls/library/ecdsa.c +++ b/thirdparty/mbedtls/library/ecdsa.c @@ -42,6 +42,186 @@ #include "mbedtls/hmac_drbg.h" #endif +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include <stdlib.h> +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include "mbedtls/platform_util.h" + +/* Parameter validation macros based on platform_util.h */ +#define ECDSA_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA ) +#define ECDSA_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +#if defined(MBEDTLS_ECP_RESTARTABLE) + +/* + * Sub-context for ecdsa_verify() + */ +struct mbedtls_ecdsa_restart_ver +{ + mbedtls_mpi u1, u2; /* intermediate values */ + enum { /* what to do next? */ + ecdsa_ver_init = 0, /* getting started */ + ecdsa_ver_muladd, /* muladd step */ + } state; +}; + +/* + * Init verify restart sub-context + */ +static void ecdsa_restart_ver_init( mbedtls_ecdsa_restart_ver_ctx *ctx ) +{ + mbedtls_mpi_init( &ctx->u1 ); + mbedtls_mpi_init( &ctx->u2 ); + ctx->state = ecdsa_ver_init; +} + +/* + * Free the components of a verify restart sub-context + */ +static void ecdsa_restart_ver_free( mbedtls_ecdsa_restart_ver_ctx *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_mpi_free( &ctx->u1 ); + mbedtls_mpi_free( &ctx->u2 ); + + ecdsa_restart_ver_init( ctx ); +} + +/* + * Sub-context for ecdsa_sign() + */ +struct mbedtls_ecdsa_restart_sig +{ + int sign_tries; + int key_tries; + mbedtls_mpi k; /* per-signature random */ + mbedtls_mpi r; /* r value */ + enum { /* what to do next? */ + ecdsa_sig_init = 0, /* getting started */ + ecdsa_sig_mul, /* doing ecp_mul() */ + ecdsa_sig_modn, /* mod N computations */ + } state; +}; + +/* + * Init verify sign sub-context + */ +static void ecdsa_restart_sig_init( mbedtls_ecdsa_restart_sig_ctx *ctx ) +{ + ctx->sign_tries = 0; + ctx->key_tries = 0; + mbedtls_mpi_init( &ctx->k ); + mbedtls_mpi_init( &ctx->r ); + ctx->state = ecdsa_sig_init; +} + +/* + * Free the components of a sign restart sub-context + */ +static void ecdsa_restart_sig_free( mbedtls_ecdsa_restart_sig_ctx *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_mpi_free( &ctx->k ); + mbedtls_mpi_free( &ctx->r ); +} + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) +/* + * Sub-context for ecdsa_sign_det() + */ +struct mbedtls_ecdsa_restart_det +{ + mbedtls_hmac_drbg_context rng_ctx; /* DRBG state */ + enum { /* what to do next? */ + ecdsa_det_init = 0, /* getting started */ + ecdsa_det_sign, /* make signature */ + } state; +}; + +/* + * Init verify sign_det sub-context + */ +static void ecdsa_restart_det_init( mbedtls_ecdsa_restart_det_ctx *ctx ) +{ + mbedtls_hmac_drbg_init( &ctx->rng_ctx ); + ctx->state = ecdsa_det_init; +} + +/* + * Free the components of a sign_det restart sub-context + */ +static void ecdsa_restart_det_free( mbedtls_ecdsa_restart_det_ctx *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_hmac_drbg_free( &ctx->rng_ctx ); + + ecdsa_restart_det_init( ctx ); +} +#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ + +#define ECDSA_RS_ECP &rs_ctx->ecp + +/* Utility macro for checking and updating ops budget */ +#define ECDSA_BUDGET( ops ) \ + MBEDTLS_MPI_CHK( mbedtls_ecp_check_budget( grp, &rs_ctx->ecp, ops ) ); + +/* Call this when entering a function that needs its own sub-context */ +#define ECDSA_RS_ENTER( SUB ) do { \ + /* reset ops count for this call if top-level */ \ + if( rs_ctx != NULL && rs_ctx->ecp.depth++ == 0 ) \ + rs_ctx->ecp.ops_done = 0; \ + \ + /* set up our own sub-context if needed */ \ + if( mbedtls_ecp_restart_is_enabled() && \ + rs_ctx != NULL && rs_ctx->SUB == NULL ) \ + { \ + rs_ctx->SUB = mbedtls_calloc( 1, sizeof( *rs_ctx->SUB ) ); \ + if( rs_ctx->SUB == NULL ) \ + return( MBEDTLS_ERR_ECP_ALLOC_FAILED ); \ + \ + ecdsa_restart_## SUB ##_init( rs_ctx->SUB ); \ + } \ +} while( 0 ) + +/* Call this when leaving a function that needs its own sub-context */ +#define ECDSA_RS_LEAVE( SUB ) do { \ + /* clear our sub-context when not in progress (done or error) */ \ + if( rs_ctx != NULL && rs_ctx->SUB != NULL && \ + ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) \ + { \ + ecdsa_restart_## SUB ##_free( rs_ctx->SUB ); \ + mbedtls_free( rs_ctx->SUB ); \ + rs_ctx->SUB = NULL; \ + } \ + \ + if( rs_ctx != NULL ) \ + rs_ctx->ecp.depth--; \ +} while( 0 ) + +#else /* MBEDTLS_ECP_RESTARTABLE */ + +#define ECDSA_RS_ECP NULL + +#define ECDSA_BUDGET( ops ) /* no-op; for compatibility */ + +#define ECDSA_RS_ENTER( SUB ) (void) rs_ctx +#define ECDSA_RS_LEAVE( SUB ) (void) rs_ctx + +#endif /* MBEDTLS_ECP_RESTARTABLE */ + /* * Derive a suitable integer for group grp from a buffer of length len * SEC1 4.1.3 step 5 aka SEC1 4.1.4 step 3 @@ -70,13 +250,17 @@ cleanup: * Compute ECDSA signature of a hashed message (SEC1 4.1.3) * Obviously, compared to SEC1 4.1.3, we skip step 4 (hash message) */ -int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, +static int ecdsa_sign_restartable( mbedtls_ecp_group *grp, + mbedtls_mpi *r, mbedtls_mpi *s, const mbedtls_mpi *d, const unsigned char *buf, size_t blen, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + mbedtls_ecdsa_restart_ctx *rs_ctx ) { - int ret, key_tries, sign_tries, blind_tries; + int ret, key_tries, sign_tries; + int *p_sign_tries = &sign_tries, *p_key_tries = &key_tries; mbedtls_ecp_point R; mbedtls_mpi k, e, t; + mbedtls_mpi *pk = &k, *pr = r; /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */ if( grp->N.p == NULL ) @@ -89,26 +273,72 @@ int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, mbedtls_ecp_point_init( &R ); mbedtls_mpi_init( &k ); mbedtls_mpi_init( &e ); mbedtls_mpi_init( &t ); - sign_tries = 0; + ECDSA_RS_ENTER( sig ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->sig != NULL ) + { + /* redirect to our context */ + p_sign_tries = &rs_ctx->sig->sign_tries; + p_key_tries = &rs_ctx->sig->key_tries; + pk = &rs_ctx->sig->k; + pr = &rs_ctx->sig->r; + + /* jump to current step */ + if( rs_ctx->sig->state == ecdsa_sig_mul ) + goto mul; + if( rs_ctx->sig->state == ecdsa_sig_modn ) + goto modn; + } +#endif /* MBEDTLS_ECP_RESTARTABLE */ + + *p_sign_tries = 0; do { + if( *p_sign_tries++ > 10 ) + { + ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; + goto cleanup; + } + /* * Steps 1-3: generate a suitable ephemeral keypair * and set r = xR mod n */ - key_tries = 0; + *p_key_tries = 0; do { - MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair( grp, &k, &R, f_rng, p_rng ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( r, &R.X, &grp->N ) ); - - if( key_tries++ > 10 ) + if( *p_key_tries++ > 10 ) { ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; goto cleanup; } + + MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, pk, f_rng, p_rng ) ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->sig != NULL ) + rs_ctx->sig->state = ecdsa_sig_mul; + +mul: +#endif + MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, &R, pk, &grp->G, + f_rng, p_rng, ECDSA_RS_ECP ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( pr, &R.X, &grp->N ) ); } - while( mbedtls_mpi_cmp_int( r, 0 ) == 0 ); + while( mbedtls_mpi_cmp_int( pr, 0 ) == 0 ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->sig != NULL ) + rs_ctx->sig->state = ecdsa_sig_modn; + +modn: +#endif + /* + * Accounting for everything up to the end of the loop + * (step 6, but checking now avoids saving e and t) + */ + ECDSA_BUDGET( MBEDTLS_ECP_OPS_INV + 4 ); /* * Step 5: derive MPI from hashed message @@ -119,57 +349,67 @@ int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, * Generate a random value to blind inv_mod in next step, * avoiding a potential timing leak. */ - blind_tries = 0; - do - { - size_t n_size = ( grp->nbits + 7 ) / 8; - MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &t, n_size, f_rng, p_rng ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &t, 8 * n_size - grp->nbits ) ); - - /* See mbedtls_ecp_gen_keypair() */ - if( ++blind_tries > 30 ) - return( MBEDTLS_ERR_ECP_RANDOM_FAILED ); - } - while( mbedtls_mpi_cmp_int( &t, 1 ) < 0 || - mbedtls_mpi_cmp_mpi( &t, &grp->N ) >= 0 ); + MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, &t, f_rng, p_rng ) ); /* * Step 6: compute s = (e + r * d) / k = t (e + rd) / (kt) mod n */ - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, r, d ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, pr, d ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &e, &e, s ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &e, &e, &t ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &k, &k, &t ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( s, &k, &grp->N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( pk, pk, &t ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( s, pk, &grp->N ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, s, &e ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( s, s, &grp->N ) ); - - if( sign_tries++ > 10 ) - { - ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; - goto cleanup; - } } while( mbedtls_mpi_cmp_int( s, 0 ) == 0 ); +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->sig != NULL ) + mbedtls_mpi_copy( r, pr ); +#endif + cleanup: mbedtls_ecp_point_free( &R ); mbedtls_mpi_free( &k ); mbedtls_mpi_free( &e ); mbedtls_mpi_free( &t ); + ECDSA_RS_LEAVE( sig ); + return( ret ); } -#endif /* MBEDTLS_ECDSA_SIGN_ALT */ + +/* + * Compute ECDSA signature of a hashed message + */ +int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, + const mbedtls_mpi *d, const unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + ECDSA_VALIDATE_RET( grp != NULL ); + ECDSA_VALIDATE_RET( r != NULL ); + ECDSA_VALIDATE_RET( s != NULL ); + ECDSA_VALIDATE_RET( d != NULL ); + ECDSA_VALIDATE_RET( f_rng != NULL ); + ECDSA_VALIDATE_RET( buf != NULL || blen == 0 ); + + return( ecdsa_sign_restartable( grp, r, s, d, buf, blen, + f_rng, p_rng, NULL ) ); +} +#endif /* !MBEDTLS_ECDSA_SIGN_ALT */ #if defined(MBEDTLS_ECDSA_DETERMINISTIC) /* * Deterministic signature wrapper */ -int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, +static int ecdsa_sign_det_restartable( mbedtls_ecp_group *grp, + mbedtls_mpi *r, mbedtls_mpi *s, const mbedtls_mpi *d, const unsigned char *buf, size_t blen, - mbedtls_md_type_t md_alg ) + mbedtls_md_type_t md_alg, + mbedtls_ecdsa_restart_ctx *rs_ctx ) { int ret; mbedtls_hmac_drbg_context rng_ctx; + mbedtls_hmac_drbg_context *p_rng = &rng_ctx; unsigned char data[2 * MBEDTLS_ECP_MAX_BYTES]; size_t grp_len = ( grp->nbits + 7 ) / 8; const mbedtls_md_info_t *md_info; @@ -181,21 +421,64 @@ int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi mbedtls_mpi_init( &h ); mbedtls_hmac_drbg_init( &rng_ctx ); + ECDSA_RS_ENTER( det ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->det != NULL ) + { + /* redirect to our context */ + p_rng = &rs_ctx->det->rng_ctx; + + /* jump to current step */ + if( rs_ctx->det->state == ecdsa_det_sign ) + goto sign; + } +#endif /* MBEDTLS_ECP_RESTARTABLE */ + /* Use private key and message hash (reduced) to initialize HMAC_DRBG */ MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( d, data, grp_len ) ); MBEDTLS_MPI_CHK( derive_mpi( grp, &h, buf, blen ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, data + grp_len, grp_len ) ); - mbedtls_hmac_drbg_seed_buf( &rng_ctx, md_info, data, 2 * grp_len ); + mbedtls_hmac_drbg_seed_buf( p_rng, md_info, data, 2 * grp_len ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->det != NULL ) + rs_ctx->det->state = ecdsa_det_sign; +sign: +#endif +#if defined(MBEDTLS_ECDSA_SIGN_ALT) ret = mbedtls_ecdsa_sign( grp, r, s, d, buf, blen, - mbedtls_hmac_drbg_random, &rng_ctx ); + mbedtls_hmac_drbg_random, p_rng ); +#else + ret = ecdsa_sign_restartable( grp, r, s, d, buf, blen, + mbedtls_hmac_drbg_random, p_rng, rs_ctx ); +#endif /* MBEDTLS_ECDSA_SIGN_ALT */ cleanup: mbedtls_hmac_drbg_free( &rng_ctx ); mbedtls_mpi_free( &h ); + ECDSA_RS_LEAVE( det ); + return( ret ); } + +/* + * Deterministic signature wrapper + */ +int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, + const mbedtls_mpi *d, const unsigned char *buf, size_t blen, + mbedtls_md_type_t md_alg ) +{ + ECDSA_VALIDATE_RET( grp != NULL ); + ECDSA_VALIDATE_RET( r != NULL ); + ECDSA_VALIDATE_RET( s != NULL ); + ECDSA_VALIDATE_RET( d != NULL ); + ECDSA_VALIDATE_RET( buf != NULL || blen == 0 ); + + return( ecdsa_sign_det_restartable( grp, r, s, d, buf, blen, md_alg, NULL ) ); +} #endif /* MBEDTLS_ECDSA_DETERMINISTIC */ #if !defined(MBEDTLS_ECDSA_VERIFY_ALT) @@ -203,21 +486,40 @@ cleanup: * Verify ECDSA signature of hashed message (SEC1 4.1.4) * Obviously, compared to SEC1 4.1.3, we skip step 2 (hash message) */ -int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp, - const unsigned char *buf, size_t blen, - const mbedtls_ecp_point *Q, const mbedtls_mpi *r, const mbedtls_mpi *s) +static int ecdsa_verify_restartable( mbedtls_ecp_group *grp, + const unsigned char *buf, size_t blen, + const mbedtls_ecp_point *Q, + const mbedtls_mpi *r, const mbedtls_mpi *s, + mbedtls_ecdsa_restart_ctx *rs_ctx ) { int ret; mbedtls_mpi e, s_inv, u1, u2; mbedtls_ecp_point R; + mbedtls_mpi *pu1 = &u1, *pu2 = &u2; mbedtls_ecp_point_init( &R ); - mbedtls_mpi_init( &e ); mbedtls_mpi_init( &s_inv ); mbedtls_mpi_init( &u1 ); mbedtls_mpi_init( &u2 ); + mbedtls_mpi_init( &e ); mbedtls_mpi_init( &s_inv ); + mbedtls_mpi_init( &u1 ); mbedtls_mpi_init( &u2 ); /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */ if( grp->N.p == NULL ) return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + ECDSA_RS_ENTER( ver ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->ver != NULL ) + { + /* redirect to our context */ + pu1 = &rs_ctx->ver->u1; + pu2 = &rs_ctx->ver->u2; + + /* jump to current step */ + if( rs_ctx->ver->state == ecdsa_ver_muladd ) + goto muladd; + } +#endif /* MBEDTLS_ECP_RESTARTABLE */ + /* * Step 1: make sure r and s are in range 1..n-1 */ @@ -229,11 +531,6 @@ int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp, } /* - * Additional precaution: make sure Q is valid - */ - MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, Q ) ); - - /* * Step 3: derive MPI from hashed message */ MBEDTLS_MPI_CHK( derive_mpi( grp, &e, buf, blen ) ); @@ -241,21 +538,27 @@ int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp, /* * Step 4: u1 = e / s mod n, u2 = r / s mod n */ + ECDSA_BUDGET( MBEDTLS_ECP_OPS_CHK + MBEDTLS_ECP_OPS_INV + 2 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &s_inv, s, &grp->N ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &u1, &e, &s_inv ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &u1, &u1, &grp->N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( pu1, &e, &s_inv ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( pu1, pu1, &grp->N ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &u2, r, &s_inv ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &u2, &u2, &grp->N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( pu2, r, &s_inv ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( pu2, pu2, &grp->N ) ); +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->ver != NULL ) + rs_ctx->ver->state = ecdsa_ver_muladd; + +muladd: +#endif /* * Step 5: R = u1 G + u2 Q - * - * Since we're not using any secret data, no need to pass a RNG to - * mbedtls_ecp_mul() for countermesures. */ - MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, &R, &u1, &grp->G, &u2, Q ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_muladd_restartable( grp, + &R, pu1, &grp->G, pu2, Q, ECDSA_RS_ECP ) ); if( mbedtls_ecp_is_zero( &R ) ) { @@ -280,11 +583,32 @@ int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp, cleanup: mbedtls_ecp_point_free( &R ); - mbedtls_mpi_free( &e ); mbedtls_mpi_free( &s_inv ); mbedtls_mpi_free( &u1 ); mbedtls_mpi_free( &u2 ); + mbedtls_mpi_free( &e ); mbedtls_mpi_free( &s_inv ); + mbedtls_mpi_free( &u1 ); mbedtls_mpi_free( &u2 ); + + ECDSA_RS_LEAVE( ver ); return( ret ); } -#endif /* MBEDTLS_ECDSA_VERIFY_ALT */ + +/* + * Verify ECDSA signature of hashed message + */ +int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp, + const unsigned char *buf, size_t blen, + const mbedtls_ecp_point *Q, + const mbedtls_mpi *r, + const mbedtls_mpi *s) +{ + ECDSA_VALIDATE_RET( grp != NULL ); + ECDSA_VALIDATE_RET( Q != NULL ); + ECDSA_VALIDATE_RET( r != NULL ); + ECDSA_VALIDATE_RET( s != NULL ); + ECDSA_VALIDATE_RET( buf != NULL || blen == 0 ); + + return( ecdsa_verify_restartable( grp, buf, blen, Q, r, s, NULL ) ); +} +#endif /* !MBEDTLS_ECDSA_VERIFY_ALT */ /* * Convert a signature (given by context) to ASN.1 @@ -313,14 +637,20 @@ static int ecdsa_signature_to_asn1( const mbedtls_mpi *r, const mbedtls_mpi *s, /* * Compute and write signature */ -int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, mbedtls_md_type_t md_alg, +int mbedtls_ecdsa_write_signature_restartable( mbedtls_ecdsa_context *ctx, + mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hlen, unsigned char *sig, size_t *slen, int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) + void *p_rng, + mbedtls_ecdsa_restart_ctx *rs_ctx ) { int ret; mbedtls_mpi r, s; + ECDSA_VALIDATE_RET( ctx != NULL ); + ECDSA_VALIDATE_RET( hash != NULL ); + ECDSA_VALIDATE_RET( sig != NULL ); + ECDSA_VALIDATE_RET( slen != NULL ); mbedtls_mpi_init( &r ); mbedtls_mpi_init( &s ); @@ -329,14 +659,19 @@ int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, mbedtls_md_type_t (void) f_rng; (void) p_rng; - MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign_det( &ctx->grp, &r, &s, &ctx->d, - hash, hlen, md_alg ) ); + MBEDTLS_MPI_CHK( ecdsa_sign_det_restartable( &ctx->grp, &r, &s, &ctx->d, + hash, hlen, md_alg, rs_ctx ) ); #else (void) md_alg; +#if defined(MBEDTLS_ECDSA_SIGN_ALT) MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign( &ctx->grp, &r, &s, &ctx->d, hash, hlen, f_rng, p_rng ) ); -#endif +#else + MBEDTLS_MPI_CHK( ecdsa_sign_restartable( &ctx->grp, &r, &s, &ctx->d, + hash, hlen, f_rng, p_rng, rs_ctx ) ); +#endif /* MBEDTLS_ECDSA_SIGN_ALT */ +#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ MBEDTLS_MPI_CHK( ecdsa_signature_to_asn1( &r, &s, sig, slen ) ); @@ -347,13 +682,35 @@ cleanup: return( ret ); } -#if ! defined(MBEDTLS_DEPRECATED_REMOVED) && \ +/* + * Compute and write signature + */ +int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hlen, + unsigned char *sig, size_t *slen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + ECDSA_VALIDATE_RET( ctx != NULL ); + ECDSA_VALIDATE_RET( hash != NULL ); + ECDSA_VALIDATE_RET( sig != NULL ); + ECDSA_VALIDATE_RET( slen != NULL ); + return( mbedtls_ecdsa_write_signature_restartable( + ctx, md_alg, hash, hlen, sig, slen, f_rng, p_rng, NULL ) ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) && \ defined(MBEDTLS_ECDSA_DETERMINISTIC) int mbedtls_ecdsa_write_signature_det( mbedtls_ecdsa_context *ctx, const unsigned char *hash, size_t hlen, unsigned char *sig, size_t *slen, mbedtls_md_type_t md_alg ) { + ECDSA_VALIDATE_RET( ctx != NULL ); + ECDSA_VALIDATE_RET( hash != NULL ); + ECDSA_VALIDATE_RET( sig != NULL ); + ECDSA_VALIDATE_RET( slen != NULL ); return( mbedtls_ecdsa_write_signature( ctx, md_alg, hash, hlen, sig, slen, NULL, NULL ) ); } @@ -366,11 +723,29 @@ int mbedtls_ecdsa_read_signature( mbedtls_ecdsa_context *ctx, const unsigned char *hash, size_t hlen, const unsigned char *sig, size_t slen ) { + ECDSA_VALIDATE_RET( ctx != NULL ); + ECDSA_VALIDATE_RET( hash != NULL ); + ECDSA_VALIDATE_RET( sig != NULL ); + return( mbedtls_ecdsa_read_signature_restartable( + ctx, hash, hlen, sig, slen, NULL ) ); +} + +/* + * Restartable read and check signature + */ +int mbedtls_ecdsa_read_signature_restartable( mbedtls_ecdsa_context *ctx, + const unsigned char *hash, size_t hlen, + const unsigned char *sig, size_t slen, + mbedtls_ecdsa_restart_ctx *rs_ctx ) +{ int ret; unsigned char *p = (unsigned char *) sig; const unsigned char *end = sig + slen; size_t len; mbedtls_mpi r, s; + ECDSA_VALIDATE_RET( ctx != NULL ); + ECDSA_VALIDATE_RET( hash != NULL ); + ECDSA_VALIDATE_RET( sig != NULL ); mbedtls_mpi_init( &r ); mbedtls_mpi_init( &s ); @@ -395,10 +770,15 @@ int mbedtls_ecdsa_read_signature( mbedtls_ecdsa_context *ctx, ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA; goto cleanup; } - +#if defined(MBEDTLS_ECDSA_VERIFY_ALT) if( ( ret = mbedtls_ecdsa_verify( &ctx->grp, hash, hlen, - &ctx->Q, &r, &s ) ) != 0 ) + &ctx->Q, &r, &s ) ) != 0 ) goto cleanup; +#else + if( ( ret = ecdsa_verify_restartable( &ctx->grp, hash, hlen, + &ctx->Q, &r, &s, rs_ctx ) ) != 0 ) + goto cleanup; +#endif /* MBEDTLS_ECDSA_VERIFY_ALT */ /* At this point we know that the buffer starts with a valid signature. * Return 0 if the buffer just contains the signature, and a specific @@ -420,10 +800,13 @@ cleanup: int mbedtls_ecdsa_genkey( mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id gid, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { + ECDSA_VALIDATE_RET( ctx != NULL ); + ECDSA_VALIDATE_RET( f_rng != NULL ); + return( mbedtls_ecp_group_load( &ctx->grp, gid ) || mbedtls_ecp_gen_keypair( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng ) ); } -#endif /* MBEDTLS_ECDSA_GENKEY_ALT */ +#endif /* !MBEDTLS_ECDSA_GENKEY_ALT */ /* * Set context from an mbedtls_ecp_keypair @@ -431,6 +814,8 @@ int mbedtls_ecdsa_genkey( mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id gid, int mbedtls_ecdsa_from_keypair( mbedtls_ecdsa_context *ctx, const mbedtls_ecp_keypair *key ) { int ret; + ECDSA_VALIDATE_RET( ctx != NULL ); + ECDSA_VALIDATE_RET( key != NULL ); if( ( ret = mbedtls_ecp_group_copy( &ctx->grp, &key->grp ) ) != 0 || ( ret = mbedtls_mpi_copy( &ctx->d, &key->d ) ) != 0 || @@ -447,6 +832,8 @@ int mbedtls_ecdsa_from_keypair( mbedtls_ecdsa_context *ctx, const mbedtls_ecp_ke */ void mbedtls_ecdsa_init( mbedtls_ecdsa_context *ctx ) { + ECDSA_VALIDATE( ctx != NULL ); + mbedtls_ecp_keypair_init( ctx ); } @@ -455,7 +842,53 @@ void mbedtls_ecdsa_init( mbedtls_ecdsa_context *ctx ) */ void mbedtls_ecdsa_free( mbedtls_ecdsa_context *ctx ) { + if( ctx == NULL ) + return; + mbedtls_ecp_keypair_free( ctx ); } +#if defined(MBEDTLS_ECP_RESTARTABLE) +/* + * Initialize a restart context + */ +void mbedtls_ecdsa_restart_init( mbedtls_ecdsa_restart_ctx *ctx ) +{ + ECDSA_VALIDATE( ctx != NULL ); + + mbedtls_ecp_restart_init( &ctx->ecp ); + + ctx->ver = NULL; + ctx->sig = NULL; +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) + ctx->det = NULL; +#endif +} + +/* + * Free the components of a restart context + */ +void mbedtls_ecdsa_restart_free( mbedtls_ecdsa_restart_ctx *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_ecp_restart_free( &ctx->ecp ); + + ecdsa_restart_ver_free( ctx->ver ); + mbedtls_free( ctx->ver ); + ctx->ver = NULL; + + ecdsa_restart_sig_free( ctx->sig ); + mbedtls_free( ctx->sig ); + ctx->sig = NULL; + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) + ecdsa_restart_det_free( ctx->det ); + mbedtls_free( ctx->det ); + ctx->det = NULL; +#endif +} +#endif /* MBEDTLS_ECP_RESTARTABLE */ + #endif /* MBEDTLS_ECDSA_C */ diff --git a/thirdparty/mbedtls/library/ecjpake.c b/thirdparty/mbedtls/library/ecjpake.c index ec5a4007db..be941b14b1 100644 --- a/thirdparty/mbedtls/library/ecjpake.c +++ b/thirdparty/mbedtls/library/ecjpake.c @@ -33,11 +33,18 @@ #if defined(MBEDTLS_ECJPAKE_C) #include "mbedtls/ecjpake.h" +#include "mbedtls/platform_util.h" #include <string.h> #if !defined(MBEDTLS_ECJPAKE_ALT) +/* Parameter validation macros based on platform_util.h */ +#define ECJPAKE_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA ) +#define ECJPAKE_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + /* * Convert a mbedtls_ecjpake_role to identifier string */ @@ -54,8 +61,7 @@ static const char * const ecjpake_id[] = { */ void mbedtls_ecjpake_init( mbedtls_ecjpake_context *ctx ) { - if( ctx == NULL ) - return; + ECJPAKE_VALIDATE( ctx != NULL ); ctx->md_info = NULL; mbedtls_ecp_group_init( &ctx->grp ); @@ -106,6 +112,11 @@ int mbedtls_ecjpake_setup( mbedtls_ecjpake_context *ctx, { int ret; + ECJPAKE_VALIDATE_RET( ctx != NULL ); + ECJPAKE_VALIDATE_RET( role == MBEDTLS_ECJPAKE_CLIENT || + role == MBEDTLS_ECJPAKE_SERVER ); + ECJPAKE_VALIDATE_RET( secret != NULL || len == 0 ); + ctx->role = role; if( ( ctx->md_info = mbedtls_md_info_from_type( hash ) ) == NULL ) @@ -127,6 +138,8 @@ cleanup: */ int mbedtls_ecjpake_check( const mbedtls_ecjpake_context *ctx ) { + ECJPAKE_VALIDATE_RET( ctx != NULL ); + if( ctx->md_info == NULL || ctx->grp.id == MBEDTLS_ECP_DP_NONE || ctx->s.p == NULL ) @@ -504,6 +517,9 @@ int mbedtls_ecjpake_read_round_one( mbedtls_ecjpake_context *ctx, const unsigned char *buf, size_t len ) { + ECJPAKE_VALIDATE_RET( ctx != NULL ); + ECJPAKE_VALIDATE_RET( buf != NULL ); + return( ecjpake_kkpp_read( ctx->md_info, &ctx->grp, ctx->point_format, &ctx->grp.G, &ctx->Xp1, &ctx->Xp2, ID_PEER, @@ -518,6 +534,11 @@ int mbedtls_ecjpake_write_round_one( mbedtls_ecjpake_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { + ECJPAKE_VALIDATE_RET( ctx != NULL ); + ECJPAKE_VALIDATE_RET( buf != NULL ); + ECJPAKE_VALIDATE_RET( olen != NULL ); + ECJPAKE_VALIDATE_RET( f_rng != NULL ); + return( ecjpake_kkpp_write( ctx->md_info, &ctx->grp, ctx->point_format, &ctx->grp.G, &ctx->xm1, &ctx->Xm1, &ctx->xm2, &ctx->Xm2, @@ -560,6 +581,9 @@ int mbedtls_ecjpake_read_round_two( mbedtls_ecjpake_context *ctx, mbedtls_ecp_group grp; mbedtls_ecp_point G; /* C: GB, S: GA */ + ECJPAKE_VALIDATE_RET( ctx != NULL ); + ECJPAKE_VALIDATE_RET( buf != NULL ); + mbedtls_ecp_group_init( &grp ); mbedtls_ecp_point_init( &G ); @@ -652,6 +676,11 @@ int mbedtls_ecjpake_write_round_two( mbedtls_ecjpake_context *ctx, const unsigned char *end = buf + len; size_t ec_len; + ECJPAKE_VALIDATE_RET( ctx != NULL ); + ECJPAKE_VALIDATE_RET( buf != NULL ); + ECJPAKE_VALIDATE_RET( olen != NULL ); + ECJPAKE_VALIDATE_RET( f_rng != NULL ); + mbedtls_ecp_point_init( &G ); mbedtls_ecp_point_init( &Xm ); mbedtls_mpi_init( &xm ); @@ -727,6 +756,11 @@ int mbedtls_ecjpake_derive_secret( mbedtls_ecjpake_context *ctx, unsigned char kx[MBEDTLS_ECP_MAX_BYTES]; size_t x_bytes; + ECJPAKE_VALIDATE_RET( ctx != NULL ); + ECJPAKE_VALIDATE_RET( buf != NULL ); + ECJPAKE_VALIDATE_RET( olen != NULL ); + ECJPAKE_VALIDATE_RET( f_rng != NULL ); + *olen = mbedtls_md_get_size( ctx->md_info ); if( len < *olen ) return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); diff --git a/thirdparty/mbedtls/library/ecp.c b/thirdparty/mbedtls/library/ecp.c index 41db3fbe5b..ecea5910e0 100644 --- a/thirdparty/mbedtls/library/ecp.c +++ b/thirdparty/mbedtls/library/ecp.c @@ -47,6 +47,35 @@ #include MBEDTLS_CONFIG_FILE #endif +/** + * \brief Function level alternative implementation. + * + * The MBEDTLS_ECP_INTERNAL_ALT macro enables alternative implementations to + * replace certain functions in this module. The alternative implementations are + * typically hardware accelerators and need to activate the hardware before the + * computation starts and deactivate it after it finishes. The + * mbedtls_internal_ecp_init() and mbedtls_internal_ecp_free() functions serve + * this purpose. + * + * To preserve the correct functionality the following conditions must hold: + * + * - The alternative implementation must be activated by + * mbedtls_internal_ecp_init() before any of the replaceable functions is + * called. + * - mbedtls_internal_ecp_free() must \b only be called when the alternative + * implementation is activated. + * - mbedtls_internal_ecp_init() must \b not be called when the alternative + * implementation is activated. + * - Public functions must not return while the alternative implementation is + * activated. + * - Replaceable functions are guarded by \c MBEDTLS_ECP_XXX_ALT macros and + * before calling them an \code if( mbedtls_internal_ecp_grp_capable( grp ) ) + * \endcode ensures that the alternative implementation supports the current + * group. + */ +#if defined(MBEDTLS_ECP_INTERNAL_ALT) +#endif + #if defined(MBEDTLS_ECP_C) #include "mbedtls/ecp.h" @@ -57,6 +86,12 @@ #if !defined(MBEDTLS_ECP_ALT) +/* Parameter validation macros based on platform_util.h */ +#define ECP_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA ) +#define ECP_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + #if defined(MBEDTLS_PLATFORM_C) #include "mbedtls/platform.h" #else @@ -82,6 +117,233 @@ static unsigned long add_count, dbl_count, mul_count; #endif +#if defined(MBEDTLS_ECP_RESTARTABLE) +/* + * Maximum number of "basic operations" to be done in a row. + * + * Default value 0 means that ECC operations will not yield. + * Note that regardless of the value of ecp_max_ops, always at + * least one step is performed before yielding. + * + * Setting ecp_max_ops=1 can be suitable for testing purposes + * as it will interrupt computation at all possible points. + */ +static unsigned ecp_max_ops = 0; + +/* + * Set ecp_max_ops + */ +void mbedtls_ecp_set_max_ops( unsigned max_ops ) +{ + ecp_max_ops = max_ops; +} + +/* + * Check if restart is enabled + */ +int mbedtls_ecp_restart_is_enabled( void ) +{ + return( ecp_max_ops != 0 ); +} + +/* + * Restart sub-context for ecp_mul_comb() + */ +struct mbedtls_ecp_restart_mul +{ + mbedtls_ecp_point R; /* current intermediate result */ + size_t i; /* current index in various loops, 0 outside */ + mbedtls_ecp_point *T; /* table for precomputed points */ + unsigned char T_size; /* number of points in table T */ + enum { /* what were we doing last time we returned? */ + ecp_rsm_init = 0, /* nothing so far, dummy initial state */ + ecp_rsm_pre_dbl, /* precompute 2^n multiples */ + ecp_rsm_pre_norm_dbl, /* normalize precomputed 2^n multiples */ + ecp_rsm_pre_add, /* precompute remaining points by adding */ + ecp_rsm_pre_norm_add, /* normalize all precomputed points */ + ecp_rsm_comb_core, /* ecp_mul_comb_core() */ + ecp_rsm_final_norm, /* do the final normalization */ + } state; +}; + +/* + * Init restart_mul sub-context + */ +static void ecp_restart_rsm_init( mbedtls_ecp_restart_mul_ctx *ctx ) +{ + mbedtls_ecp_point_init( &ctx->R ); + ctx->i = 0; + ctx->T = NULL; + ctx->T_size = 0; + ctx->state = ecp_rsm_init; +} + +/* + * Free the components of a restart_mul sub-context + */ +static void ecp_restart_rsm_free( mbedtls_ecp_restart_mul_ctx *ctx ) +{ + unsigned char i; + + if( ctx == NULL ) + return; + + mbedtls_ecp_point_free( &ctx->R ); + + if( ctx->T != NULL ) + { + for( i = 0; i < ctx->T_size; i++ ) + mbedtls_ecp_point_free( ctx->T + i ); + mbedtls_free( ctx->T ); + } + + ecp_restart_rsm_init( ctx ); +} + +/* + * Restart context for ecp_muladd() + */ +struct mbedtls_ecp_restart_muladd +{ + mbedtls_ecp_point mP; /* mP value */ + mbedtls_ecp_point R; /* R intermediate result */ + enum { /* what should we do next? */ + ecp_rsma_mul1 = 0, /* first multiplication */ + ecp_rsma_mul2, /* second multiplication */ + ecp_rsma_add, /* addition */ + ecp_rsma_norm, /* normalization */ + } state; +}; + +/* + * Init restart_muladd sub-context + */ +static void ecp_restart_ma_init( mbedtls_ecp_restart_muladd_ctx *ctx ) +{ + mbedtls_ecp_point_init( &ctx->mP ); + mbedtls_ecp_point_init( &ctx->R ); + ctx->state = ecp_rsma_mul1; +} + +/* + * Free the components of a restart_muladd sub-context + */ +static void ecp_restart_ma_free( mbedtls_ecp_restart_muladd_ctx *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_ecp_point_free( &ctx->mP ); + mbedtls_ecp_point_free( &ctx->R ); + + ecp_restart_ma_init( ctx ); +} + +/* + * Initialize a restart context + */ +void mbedtls_ecp_restart_init( mbedtls_ecp_restart_ctx *ctx ) +{ + ECP_VALIDATE( ctx != NULL ); + ctx->ops_done = 0; + ctx->depth = 0; + ctx->rsm = NULL; + ctx->ma = NULL; +} + +/* + * Free the components of a restart context + */ +void mbedtls_ecp_restart_free( mbedtls_ecp_restart_ctx *ctx ) +{ + if( ctx == NULL ) + return; + + ecp_restart_rsm_free( ctx->rsm ); + mbedtls_free( ctx->rsm ); + + ecp_restart_ma_free( ctx->ma ); + mbedtls_free( ctx->ma ); + + mbedtls_ecp_restart_init( ctx ); +} + +/* + * Check if we can do the next step + */ +int mbedtls_ecp_check_budget( const mbedtls_ecp_group *grp, + mbedtls_ecp_restart_ctx *rs_ctx, + unsigned ops ) +{ + ECP_VALIDATE_RET( grp != NULL ); + + if( rs_ctx != NULL && ecp_max_ops != 0 ) + { + /* scale depending on curve size: the chosen reference is 256-bit, + * and multiplication is quadratic. Round to the closest integer. */ + if( grp->pbits >= 512 ) + ops *= 4; + else if( grp->pbits >= 384 ) + ops *= 2; + + /* Avoid infinite loops: always allow first step. + * Because of that, however, it's not generally true + * that ops_done <= ecp_max_ops, so the check + * ops_done > ecp_max_ops below is mandatory. */ + if( ( rs_ctx->ops_done != 0 ) && + ( rs_ctx->ops_done > ecp_max_ops || + ops > ecp_max_ops - rs_ctx->ops_done ) ) + { + return( MBEDTLS_ERR_ECP_IN_PROGRESS ); + } + + /* update running count */ + rs_ctx->ops_done += ops; + } + + return( 0 ); +} + +/* Call this when entering a function that needs its own sub-context */ +#define ECP_RS_ENTER( SUB ) do { \ + /* reset ops count for this call if top-level */ \ + if( rs_ctx != NULL && rs_ctx->depth++ == 0 ) \ + rs_ctx->ops_done = 0; \ + \ + /* set up our own sub-context if needed */ \ + if( mbedtls_ecp_restart_is_enabled() && \ + rs_ctx != NULL && rs_ctx->SUB == NULL ) \ + { \ + rs_ctx->SUB = mbedtls_calloc( 1, sizeof( *rs_ctx->SUB ) ); \ + if( rs_ctx->SUB == NULL ) \ + return( MBEDTLS_ERR_ECP_ALLOC_FAILED ); \ + \ + ecp_restart_## SUB ##_init( rs_ctx->SUB ); \ + } \ +} while( 0 ) + +/* Call this when leaving a function that needs its own sub-context */ +#define ECP_RS_LEAVE( SUB ) do { \ + /* clear our sub-context when not in progress (done or error) */ \ + if( rs_ctx != NULL && rs_ctx->SUB != NULL && \ + ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) \ + { \ + ecp_restart_## SUB ##_free( rs_ctx->SUB ); \ + mbedtls_free( rs_ctx->SUB ); \ + rs_ctx->SUB = NULL; \ + } \ + \ + if( rs_ctx != NULL ) \ + rs_ctx->depth--; \ +} while( 0 ) + +#else /* MBEDTLS_ECP_RESTARTABLE */ + +#define ECP_RS_ENTER( sub ) (void) rs_ctx; +#define ECP_RS_LEAVE( sub ) (void) rs_ctx; + +#endif /* MBEDTLS_ECP_RESTARTABLE */ + #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ @@ -243,6 +505,9 @@ const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_name( const char *name { const mbedtls_ecp_curve_info *curve_info; + if( name == NULL ) + return( NULL ); + for( curve_info = mbedtls_ecp_curve_list(); curve_info->grp_id != MBEDTLS_ECP_DP_NONE; curve_info++ ) @@ -273,8 +538,7 @@ static inline ecp_curve_type ecp_get_type( const mbedtls_ecp_group *grp ) */ void mbedtls_ecp_point_init( mbedtls_ecp_point *pt ) { - if( pt == NULL ) - return; + ECP_VALIDATE( pt != NULL ); mbedtls_mpi_init( &pt->X ); mbedtls_mpi_init( &pt->Y ); @@ -286,10 +550,23 @@ void mbedtls_ecp_point_init( mbedtls_ecp_point *pt ) */ void mbedtls_ecp_group_init( mbedtls_ecp_group *grp ) { - if( grp == NULL ) - return; - - memset( grp, 0, sizeof( mbedtls_ecp_group ) ); + ECP_VALIDATE( grp != NULL ); + + grp->id = MBEDTLS_ECP_DP_NONE; + mbedtls_mpi_init( &grp->P ); + mbedtls_mpi_init( &grp->A ); + mbedtls_mpi_init( &grp->B ); + mbedtls_ecp_point_init( &grp->G ); + mbedtls_mpi_init( &grp->N ); + grp->pbits = 0; + grp->nbits = 0; + grp->h = 0; + grp->modp = NULL; + grp->t_pre = NULL; + grp->t_post = NULL; + grp->t_data = NULL; + grp->T = NULL; + grp->T_size = 0; } /* @@ -297,8 +574,7 @@ void mbedtls_ecp_group_init( mbedtls_ecp_group *grp ) */ void mbedtls_ecp_keypair_init( mbedtls_ecp_keypair *key ) { - if( key == NULL ) - return; + ECP_VALIDATE( key != NULL ); mbedtls_ecp_group_init( &key->grp ); mbedtls_mpi_init( &key->d ); @@ -366,6 +642,8 @@ void mbedtls_ecp_keypair_free( mbedtls_ecp_keypair *key ) int mbedtls_ecp_copy( mbedtls_ecp_point *P, const mbedtls_ecp_point *Q ) { int ret; + ECP_VALIDATE_RET( P != NULL ); + ECP_VALIDATE_RET( Q != NULL ); MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->X, &Q->X ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->Y, &Q->Y ) ); @@ -380,7 +658,10 @@ cleanup: */ int mbedtls_ecp_group_copy( mbedtls_ecp_group *dst, const mbedtls_ecp_group *src ) { - return mbedtls_ecp_group_load( dst, src->id ); + ECP_VALIDATE_RET( dst != NULL ); + ECP_VALIDATE_RET( src != NULL ); + + return( mbedtls_ecp_group_load( dst, src->id ) ); } /* @@ -389,6 +670,7 @@ int mbedtls_ecp_group_copy( mbedtls_ecp_group *dst, const mbedtls_ecp_group *src int mbedtls_ecp_set_zero( mbedtls_ecp_point *pt ) { int ret; + ECP_VALIDATE_RET( pt != NULL ); MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->X , 1 ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Y , 1 ) ); @@ -403,15 +685,20 @@ cleanup: */ int mbedtls_ecp_is_zero( mbedtls_ecp_point *pt ) { + ECP_VALIDATE_RET( pt != NULL ); + return( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 ); } /* - * Compare two points lazyly + * Compare two points lazily */ int mbedtls_ecp_point_cmp( const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q ) { + ECP_VALIDATE_RET( P != NULL ); + ECP_VALIDATE_RET( Q != NULL ); + if( mbedtls_mpi_cmp_mpi( &P->X, &Q->X ) == 0 && mbedtls_mpi_cmp_mpi( &P->Y, &Q->Y ) == 0 && mbedtls_mpi_cmp_mpi( &P->Z, &Q->Z ) == 0 ) @@ -429,6 +716,9 @@ int mbedtls_ecp_point_read_string( mbedtls_ecp_point *P, int radix, const char *x, const char *y ) { int ret; + ECP_VALIDATE_RET( P != NULL ); + ECP_VALIDATE_RET( x != NULL ); + ECP_VALIDATE_RET( y != NULL ); MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P->X, radix, x ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P->Y, radix, y ) ); @@ -441,16 +731,19 @@ cleanup: /* * Export a point into unsigned binary data (SEC1 2.3.3) */ -int mbedtls_ecp_point_write_binary( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *P, - int format, size_t *olen, - unsigned char *buf, size_t buflen ) +int mbedtls_ecp_point_write_binary( const mbedtls_ecp_group *grp, + const mbedtls_ecp_point *P, + int format, size_t *olen, + unsigned char *buf, size_t buflen ) { int ret = 0; size_t plen; - - if( format != MBEDTLS_ECP_PF_UNCOMPRESSED && - format != MBEDTLS_ECP_PF_COMPRESSED ) - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( P != NULL ); + ECP_VALIDATE_RET( olen != NULL ); + ECP_VALIDATE_RET( buf != NULL ); + ECP_VALIDATE_RET( format == MBEDTLS_ECP_PF_UNCOMPRESSED || + format == MBEDTLS_ECP_PF_COMPRESSED ); /* * Common case: P == 0 @@ -497,11 +790,15 @@ cleanup: /* * Import a point from unsigned binary data (SEC1 2.3.4) */ -int mbedtls_ecp_point_read_binary( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt, - const unsigned char *buf, size_t ilen ) +int mbedtls_ecp_point_read_binary( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *pt, + const unsigned char *buf, size_t ilen ) { int ret; size_t plen; + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( pt != NULL ); + ECP_VALIDATE_RET( buf != NULL ); if( ilen < 1 ) return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); @@ -536,11 +833,16 @@ cleanup: * opaque point <1..2^8-1>; * } ECPoint; */ -int mbedtls_ecp_tls_read_point( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt, - const unsigned char **buf, size_t buf_len ) +int mbedtls_ecp_tls_read_point( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *pt, + const unsigned char **buf, size_t buf_len ) { unsigned char data_len; const unsigned char *buf_start; + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( pt != NULL ); + ECP_VALIDATE_RET( buf != NULL ); + ECP_VALIDATE_RET( *buf != NULL ); /* * We must have at least two bytes (1 for length, at least one for data) @@ -558,7 +860,7 @@ int mbedtls_ecp_tls_read_point( const mbedtls_ecp_group *grp, mbedtls_ecp_point buf_start = *buf; *buf += data_len; - return mbedtls_ecp_point_read_binary( grp, pt, buf_start, data_len ); + return( mbedtls_ecp_point_read_binary( grp, pt, buf_start, data_len ) ); } /* @@ -572,6 +874,12 @@ int mbedtls_ecp_tls_write_point( const mbedtls_ecp_group *grp, const mbedtls_ecp unsigned char *buf, size_t blen ) { int ret; + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( pt != NULL ); + ECP_VALIDATE_RET( olen != NULL ); + ECP_VALIDATE_RET( buf != NULL ); + ECP_VALIDATE_RET( format == MBEDTLS_ECP_PF_UNCOMPRESSED || + format == MBEDTLS_ECP_PF_COMPRESSED ); /* * buffer length must be at least one, for our length byte @@ -595,10 +903,33 @@ int mbedtls_ecp_tls_write_point( const mbedtls_ecp_group *grp, const mbedtls_ecp /* * Set a group from an ECParameters record (RFC 4492) */ -int mbedtls_ecp_tls_read_group( mbedtls_ecp_group *grp, const unsigned char **buf, size_t len ) +int mbedtls_ecp_tls_read_group( mbedtls_ecp_group *grp, + const unsigned char **buf, size_t len ) +{ + int ret; + mbedtls_ecp_group_id grp_id; + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( buf != NULL ); + ECP_VALIDATE_RET( *buf != NULL ); + + if( ( ret = mbedtls_ecp_tls_read_group_id( &grp_id, buf, len ) ) != 0 ) + return( ret ); + + return( mbedtls_ecp_group_load( grp, grp_id ) ); +} + +/* + * Read a group id from an ECParameters record (RFC 4492) and convert it to + * mbedtls_ecp_group_id. + */ +int mbedtls_ecp_tls_read_group_id( mbedtls_ecp_group_id *grp, + const unsigned char **buf, size_t len ) { uint16_t tls_id; const mbedtls_ecp_curve_info *curve_info; + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( buf != NULL ); + ECP_VALIDATE_RET( *buf != NULL ); /* * We expect at least three bytes (see below) @@ -622,7 +953,9 @@ int mbedtls_ecp_tls_read_group( mbedtls_ecp_group *grp, const unsigned char **bu if( ( curve_info = mbedtls_ecp_curve_info_from_tls_id( tls_id ) ) == NULL ) return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); - return mbedtls_ecp_group_load( grp, curve_info->grp_id ); + *grp = curve_info->grp_id; + + return( 0 ); } /* @@ -632,6 +965,9 @@ int mbedtls_ecp_tls_write_group( const mbedtls_ecp_group *grp, size_t *olen, unsigned char *buf, size_t blen ) { const mbedtls_ecp_curve_info *curve_info; + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( buf != NULL ); + ECP_VALIDATE_RET( olen != NULL ); if( ( curve_info = mbedtls_ecp_curve_info_from_grp_id( grp->id ) ) == NULL ) return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); @@ -752,11 +1088,10 @@ static int ecp_normalize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *p return( 0 ); #if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) - if ( mbedtls_internal_ecp_grp_capable( grp ) ) - { - return mbedtls_internal_ecp_normalize_jac( grp, pt ); - } + if( mbedtls_internal_ecp_grp_capable( grp ) ) + return( mbedtls_internal_ecp_normalize_jac( grp, pt ) ); #endif /* MBEDTLS_ECP_NORMALIZE_JAC_ALT */ + mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi ); /* @@ -796,32 +1131,33 @@ cleanup: * Cost: 1N(t) := 1I + (6t - 3)M + 1S */ static int ecp_normalize_jac_many( const mbedtls_ecp_group *grp, - mbedtls_ecp_point *T[], size_t t_len ) + mbedtls_ecp_point *T[], size_t T_size ) { int ret; size_t i; mbedtls_mpi *c, u, Zi, ZZi; - if( t_len < 2 ) + if( T_size < 2 ) return( ecp_normalize_jac( grp, *T ) ); #if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) - if ( mbedtls_internal_ecp_grp_capable( grp ) ) - { - return mbedtls_internal_ecp_normalize_jac_many(grp, T, t_len); - } + if( mbedtls_internal_ecp_grp_capable( grp ) ) + return( mbedtls_internal_ecp_normalize_jac_many( grp, T, T_size ) ); #endif - if( ( c = mbedtls_calloc( t_len, sizeof( mbedtls_mpi ) ) ) == NULL ) + if( ( c = mbedtls_calloc( T_size, sizeof( mbedtls_mpi ) ) ) == NULL ) return( MBEDTLS_ERR_ECP_ALLOC_FAILED ); + for( i = 0; i < T_size; i++ ) + mbedtls_mpi_init( &c[i] ); + mbedtls_mpi_init( &u ); mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi ); /* * c[i] = Z_0 * ... * Z_i */ MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &c[0], &T[0]->Z ) ); - for( i = 1; i < t_len; i++ ) + for( i = 1; i < T_size; i++ ) { MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &c[i], &c[i-1], &T[i]->Z ) ); MOD_MUL( c[i] ); @@ -830,9 +1166,9 @@ static int ecp_normalize_jac_many( const mbedtls_ecp_group *grp, /* * u = 1 / (Z_0 * ... * Z_n) mod P */ - MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &u, &c[t_len-1], &grp->P ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &u, &c[T_size-1], &grp->P ) ); - for( i = t_len - 1; ; i-- ) + for( i = T_size - 1; ; i-- ) { /* * Zi = 1 / Z_i mod p @@ -872,7 +1208,7 @@ static int ecp_normalize_jac_many( const mbedtls_ecp_group *grp, cleanup: mbedtls_mpi_free( &u ); mbedtls_mpi_free( &Zi ); mbedtls_mpi_free( &ZZi ); - for( i = 0; i < t_len; i++ ) + for( i = 0; i < T_size; i++ ) mbedtls_mpi_free( &c[i] ); mbedtls_free( c ); @@ -929,10 +1265,8 @@ static int ecp_double_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, #endif #if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) - if ( mbedtls_internal_ecp_grp_capable( grp ) ) - { - return mbedtls_internal_ecp_double_jac( grp, R, P ); - } + if( mbedtls_internal_ecp_grp_capable( grp ) ) + return( mbedtls_internal_ecp_double_jac( grp, R, P ) ); #endif /* MBEDTLS_ECP_DOUBLE_JAC_ALT */ mbedtls_mpi_init( &M ); mbedtls_mpi_init( &S ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &U ); @@ -1027,10 +1361,8 @@ static int ecp_add_mixed( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, #endif #if defined(MBEDTLS_ECP_ADD_MIXED_ALT) - if ( mbedtls_internal_ecp_grp_capable( grp ) ) - { - return mbedtls_internal_ecp_add_mixed( grp, R, P, Q ); - } + if( mbedtls_internal_ecp_grp_capable( grp ) ) + return( mbedtls_internal_ecp_add_mixed( grp, R, P, Q ) ); #endif /* MBEDTLS_ECP_ADD_MIXED_ALT */ /* @@ -1114,10 +1446,8 @@ static int ecp_randomize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *p int count = 0; #if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) - if ( mbedtls_internal_ecp_grp_capable( grp ) ) - { - return mbedtls_internal_ecp_randomize_jac( grp, pt, f_rng, p_rng ); - } + if( mbedtls_internal_ecp_grp_capable( grp ) ) + return( mbedtls_internal_ecp_randomize_jac( grp, pt, f_rng, p_rng ) ); #endif /* MBEDTLS_ECP_RANDOMIZE_JAC_ALT */ p_size = ( grp->pbits + 7 ) / 8; @@ -1173,11 +1503,38 @@ cleanup: * modified version that provides resistance to SPA by avoiding zero * digits in the representation as in [3]. We modify the method further by * requiring that all K_i be odd, which has the small cost that our - * representation uses one more K_i, due to carries. + * representation uses one more K_i, due to carries, but saves on the size of + * the precomputed table. * - * Also, for the sake of compactness, only the seven low-order bits of x[i] - * are used to represent K_i, and the msb of x[i] encodes the the sign (s_i in - * the paper): it is set if and only if if s_i == -1; + * Summary of the comb method and its modifications: + * + * - The goal is to compute m*P for some w*d-bit integer m. + * + * - The basic comb method splits m into the w-bit integers + * x[0] .. x[d-1] where x[i] consists of the bits in m whose + * index has residue i modulo d, and computes m * P as + * S[x[0]] + 2 * S[x[1]] + .. + 2^(d-1) S[x[d-1]], where + * S[i_{w-1} .. i_0] := i_{w-1} 2^{(w-1)d} P + ... + i_1 2^d P + i_0 P. + * + * - If it happens that, say, x[i+1]=0 (=> S[x[i+1]]=0), one can replace the sum by + * .. + 2^{i-1} S[x[i-1]] - 2^i S[x[i]] + 2^{i+1} S[x[i]] + 2^{i+2} S[x[i+2]] .., + * thereby successively converting it into a form where all summands + * are nonzero, at the cost of negative summands. This is the basic idea of [3]. + * + * - More generally, even if x[i+1] != 0, we can first transform the sum as + * .. - 2^i S[x[i]] + 2^{i+1} ( S[x[i]] + S[x[i+1]] ) + 2^{i+2} S[x[i+2]] .., + * and then replace S[x[i]] + S[x[i+1]] = S[x[i] ^ x[i+1]] + 2 S[x[i] & x[i+1]]. + * Performing and iterating this procedure for those x[i] that are even + * (keeping track of carry), we can transform the original sum into one of the form + * S[x'[0]] +- 2 S[x'[1]] +- .. +- 2^{d-1} S[x'[d-1]] + 2^d S[x'[d]] + * with all x'[i] odd. It is therefore only necessary to know S at odd indices, + * which is why we are only computing half of it in the first place in + * ecp_precompute_comb and accessing it with index abs(i) / 2 in ecp_select_comb. + * + * - For the sake of compactness, only the seven low-order bits of x[i] + * are used to represent its absolute value (K_i in the paper), and the msb + * of x[i] encodes the sign (s_i in the paper): it is set if and only if + * if s_i == -1; * * Calling conventions: * - x is an array of size d + 1 @@ -1186,8 +1543,8 @@ cleanup: * - m is the MPI, expected to be odd and such that bitlength(m) <= w * d * (the result will be incorrect if these assumptions are not satisfied) */ -static void ecp_comb_fixed( unsigned char x[], size_t d, - unsigned char w, const mbedtls_mpi *m ) +static void ecp_comb_recode_core( unsigned char x[], size_t d, + unsigned char w, const mbedtls_mpi *m ) { size_t i, j; unsigned char c, cc, adjust; @@ -1217,70 +1574,178 @@ static void ecp_comb_fixed( unsigned char x[], size_t d, } /* - * Precompute points for the comb method + * Precompute points for the adapted comb method * - * If i = i_{w-1} ... i_1 is the binary representation of i, then - * T[i] = i_{w-1} 2^{(w-1)d} P + ... + i_1 2^d P + P + * Assumption: T must be able to hold 2^{w - 1} elements. * - * T must be able to hold 2^{w - 1} elements + * Operation: If i = i_{w-1} ... i_1 is the binary representation of i, + * sets T[i] = i_{w-1} 2^{(w-1)d} P + ... + i_1 2^d P + P. * * Cost: d(w-1) D + (2^{w-1} - 1) A + 1 N(w-1) + 1 N(2^{w-1} - 1) + * + * Note: Even comb values (those where P would be omitted from the + * sum defining T[i] above) are not needed in our adaption + * the comb method. See ecp_comb_recode_core(). + * + * This function currently works in four steps: + * (1) [dbl] Computation of intermediate T[i] for 2-power values of i + * (2) [norm_dbl] Normalization of coordinates of these T[i] + * (3) [add] Computation of all T[i] + * (4) [norm_add] Normalization of all T[i] + * + * Step 1 can be interrupted but not the others; together with the final + * coordinate normalization they are the largest steps done at once, depending + * on the window size. Here are operation counts for P-256: + * + * step (2) (3) (4) + * w = 5 142 165 208 + * w = 4 136 77 160 + * w = 3 130 33 136 + * w = 2 124 11 124 + * + * So if ECC operations are blocking for too long even with a low max_ops + * value, it's useful to set MBEDTLS_ECP_WINDOW_SIZE to a lower value in order + * to minimize maximum blocking time. */ static int ecp_precompute_comb( const mbedtls_ecp_group *grp, mbedtls_ecp_point T[], const mbedtls_ecp_point *P, - unsigned char w, size_t d ) + unsigned char w, size_t d, + mbedtls_ecp_restart_ctx *rs_ctx ) { int ret; - unsigned char i, k; - size_t j; + unsigned char i; + size_t j = 0; + const unsigned char T_size = 1U << ( w - 1 ); mbedtls_ecp_point *cur, *TT[COMB_MAX_PRE - 1]; +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + { + if( rs_ctx->rsm->state == ecp_rsm_pre_dbl ) + goto dbl; + if( rs_ctx->rsm->state == ecp_rsm_pre_norm_dbl ) + goto norm_dbl; + if( rs_ctx->rsm->state == ecp_rsm_pre_add ) + goto add; + if( rs_ctx->rsm->state == ecp_rsm_pre_norm_add ) + goto norm_add; + } +#else + (void) rs_ctx; +#endif + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + { + rs_ctx->rsm->state = ecp_rsm_pre_dbl; + + /* initial state for the loop */ + rs_ctx->rsm->i = 0; + } + +dbl: +#endif /* * Set T[0] = P and * T[2^{l-1}] = 2^{dl} P for l = 1 .. w-1 (this is not the final value) */ MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &T[0], P ) ); - k = 0; - for( i = 1; i < ( 1U << ( w - 1 ) ); i <<= 1 ) +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->i != 0 ) + j = rs_ctx->rsm->i; + else +#endif + j = 0; + + for( ; j < d * ( w - 1 ); j++ ) { + MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_DBL ); + + i = 1U << ( j / d ); cur = T + i; - MBEDTLS_MPI_CHK( mbedtls_ecp_copy( cur, T + ( i >> 1 ) ) ); - for( j = 0; j < d; j++ ) - MBEDTLS_MPI_CHK( ecp_double_jac( grp, cur, cur ) ); - TT[k++] = cur; + if( j % d == 0 ) + MBEDTLS_MPI_CHK( mbedtls_ecp_copy( cur, T + ( i >> 1 ) ) ); + + MBEDTLS_MPI_CHK( ecp_double_jac( grp, cur, cur ) ); } - MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, k ) ); +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + rs_ctx->rsm->state = ecp_rsm_pre_norm_dbl; +norm_dbl: +#endif + /* + * Normalize current elements in T. As T has holes, + * use an auxiliary array of pointers to elements in T. + */ + j = 0; + for( i = 1; i < T_size; i <<= 1 ) + TT[j++] = T + i; + + MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV + 6 * j - 2 ); + + MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, j ) ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + rs_ctx->rsm->state = ecp_rsm_pre_add; + +add: +#endif /* * Compute the remaining ones using the minimal number of additions * Be careful to update T[2^l] only after using it! */ - k = 0; - for( i = 1; i < ( 1U << ( w - 1 ) ); i <<= 1 ) + MBEDTLS_ECP_BUDGET( ( T_size - 1 ) * MBEDTLS_ECP_OPS_ADD ); + + for( i = 1; i < T_size; i <<= 1 ) { j = i; while( j-- ) - { MBEDTLS_MPI_CHK( ecp_add_mixed( grp, &T[i + j], &T[j], &T[i] ) ); - TT[k++] = &T[i + j]; - } } - MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, k ) ); +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + rs_ctx->rsm->state = ecp_rsm_pre_norm_add; + +norm_add: +#endif + /* + * Normalize final elements in T. Even though there are no holes now, we + * still need the auxiliary array for homogeneity with the previous + * call. Also, skip T[0] which is already normalised, being a copy of P. + */ + for( j = 0; j + 1 < T_size; j++ ) + TT[j] = T + j + 1; + + MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV + 6 * j - 2 ); + + MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, j ) ); cleanup: +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL && + ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + { + if( rs_ctx->rsm->state == ecp_rsm_pre_dbl ) + rs_ctx->rsm->i = j; + } +#endif return( ret ); } /* * Select precomputed point: R = sign(i) * T[ abs(i) / 2 ] + * + * See ecp_comb_recode_core() for background */ static int ecp_select_comb( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, - const mbedtls_ecp_point T[], unsigned char t_len, + const mbedtls_ecp_point T[], unsigned char T_size, unsigned char i ) { int ret; @@ -1290,7 +1755,7 @@ static int ecp_select_comb( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, ii = ( i & 0x7Fu ) >> 1; /* Read the whole table to thwart cache-based timing attacks */ - for( j = 0; j < t_len; j++ ) + for( j = 0; j < T_size; j++ ) { MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->X, &T[j].X, j == ii ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->Y, &T[j].Y, j == ii ) ); @@ -1310,10 +1775,11 @@ cleanup: * Cost: d A + d D + 1 R */ static int ecp_mul_comb_core( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, - const mbedtls_ecp_point T[], unsigned char t_len, + const mbedtls_ecp_point T[], unsigned char T_size, const unsigned char x[], size_t d, int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) + void *p_rng, + mbedtls_ecp_restart_ctx *rs_ctx ) { int ret; mbedtls_ecp_point Txi; @@ -1321,17 +1787,42 @@ static int ecp_mul_comb_core( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R mbedtls_ecp_point_init( &Txi ); - /* Start with a non-zero point and randomize its coordinates */ - i = d; - MBEDTLS_MPI_CHK( ecp_select_comb( grp, R, T, t_len, x[i] ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 1 ) ); - if( f_rng != 0 ) - MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, R, f_rng, p_rng ) ); +#if !defined(MBEDTLS_ECP_RESTARTABLE) + (void) rs_ctx; +#endif + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL && + rs_ctx->rsm->state != ecp_rsm_comb_core ) + { + rs_ctx->rsm->i = 0; + rs_ctx->rsm->state = ecp_rsm_comb_core; + } + + /* new 'if' instead of nested for the sake of the 'else' branch */ + if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->i != 0 ) + { + /* restore current index (R already pointing to rs_ctx->rsm->R) */ + i = rs_ctx->rsm->i; + } + else +#endif + { + /* Start with a non-zero point and randomize its coordinates */ + i = d; + MBEDTLS_MPI_CHK( ecp_select_comb( grp, R, T, T_size, x[i] ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 1 ) ); + if( f_rng != 0 ) + MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, R, f_rng, p_rng ) ); + } - while( i-- != 0 ) + while( i != 0 ) { + MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_DBL + MBEDTLS_ECP_OPS_ADD ); + --i; + MBEDTLS_MPI_CHK( ecp_double_jac( grp, R, R ) ); - MBEDTLS_MPI_CHK( ecp_select_comb( grp, &Txi, T, t_len, x[i] ) ); + MBEDTLS_MPI_CHK( ecp_select_comb( grp, &Txi, T, T_size, x[i] ) ); MBEDTLS_MPI_CHK( ecp_add_mixed( grp, R, R, &Txi ) ); } @@ -1339,32 +1830,130 @@ cleanup: mbedtls_ecp_point_free( &Txi ); +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL && + ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + { + rs_ctx->rsm->i = i; + /* no need to save R, already pointing to rs_ctx->rsm->R */ + } +#endif + return( ret ); } /* - * Multiplication using the comb method, - * for curves in short Weierstrass form - */ -static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, - const mbedtls_mpi *m, const mbedtls_ecp_point *P, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) + * Recode the scalar to get constant-time comb multiplication + * + * As the actual scalar recoding needs an odd scalar as a starting point, + * this wrapper ensures that by replacing m by N - m if necessary, and + * informs the caller that the result of multiplication will be negated. + * + * This works because we only support large prime order for Short Weierstrass + * curves, so N is always odd hence either m or N - m is. + * + * See ecp_comb_recode_core() for background. + */ +static int ecp_comb_recode_scalar( const mbedtls_ecp_group *grp, + const mbedtls_mpi *m, + unsigned char k[COMB_MAX_D + 1], + size_t d, + unsigned char w, + unsigned char *parity_trick ) { int ret; - unsigned char w, m_is_odd, p_eq_g, pre_len, i; - size_t d; - unsigned char k[COMB_MAX_D + 1]; - mbedtls_ecp_point *T; mbedtls_mpi M, mm; mbedtls_mpi_init( &M ); mbedtls_mpi_init( &mm ); - /* we need N to be odd to trnaform m in an odd number, check now */ + /* N is always odd (see above), just make extra sure */ if( mbedtls_mpi_get_bit( &grp->N, 0 ) != 1 ) return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + /* do we need the parity trick? */ + *parity_trick = ( mbedtls_mpi_get_bit( m, 0 ) == 0 ); + + /* execute parity fix in constant time */ + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &M, m ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mm, &grp->N, m ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &M, &mm, *parity_trick ) ); + + /* actual scalar recoding */ + ecp_comb_recode_core( k, d, w, &M ); + +cleanup: + mbedtls_mpi_free( &mm ); + mbedtls_mpi_free( &M ); + + return( ret ); +} + +/* + * Perform comb multiplication (for short Weierstrass curves) + * once the auxiliary table has been pre-computed. + * + * Scalar recoding may use a parity trick that makes us compute -m * P, + * if that is the case we'll need to recover m * P at the end. + */ +static int ecp_mul_comb_after_precomp( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *R, + const mbedtls_mpi *m, + const mbedtls_ecp_point *T, + unsigned char T_size, + unsigned char w, + size_t d, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_ecp_restart_ctx *rs_ctx ) +{ + int ret; + unsigned char parity_trick; + unsigned char k[COMB_MAX_D + 1]; + mbedtls_ecp_point *RR = R; + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + { + RR = &rs_ctx->rsm->R; + + if( rs_ctx->rsm->state == ecp_rsm_final_norm ) + goto final_norm; + } +#endif + + MBEDTLS_MPI_CHK( ecp_comb_recode_scalar( grp, m, k, d, w, + &parity_trick ) ); + MBEDTLS_MPI_CHK( ecp_mul_comb_core( grp, RR, T, T_size, k, d, + f_rng, p_rng, rs_ctx ) ); + MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, RR, parity_trick ) ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + rs_ctx->rsm->state = ecp_rsm_final_norm; + +final_norm: +#endif + MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV ); + MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, RR ) ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, RR ) ); +#endif + +cleanup: + return( ret ); +} + +/* + * Pick window size based on curve size and whether we optimize for base point + */ +static unsigned char ecp_pick_window_size( const mbedtls_ecp_group *grp, + unsigned char p_eq_g ) +{ + unsigned char w; + /* * Minimize the number of multiplications, that is minimize * 10 * d * w + 18 * 2^(w-1) + 11 * d + 7 * w, with d = ceil( nbits / w ) @@ -1377,14 +1966,8 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, * Just adding one avoids upping the cost of the first mul too much, * and the memory cost too. */ -#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 - p_eq_g = ( mbedtls_mpi_cmp_mpi( &P->Y, &grp->G.Y ) == 0 && - mbedtls_mpi_cmp_mpi( &P->X, &grp->G.X ) == 0 ); if( p_eq_g ) w++; -#else - p_eq_g = 0; -#endif /* * Make sure w is within bounds. @@ -1395,70 +1978,140 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, if( w >= grp->nbits ) w = 2; - /* Other sizes that depend on w */ - pre_len = 1U << ( w - 1 ); + return( w ); +} + +/* + * Multiplication using the comb method - for curves in short Weierstrass form + * + * This function is mainly responsible for administrative work: + * - managing the restart context if enabled + * - managing the table of precomputed points (passed between the below two + * functions): allocation, computation, ownership tranfer, freeing. + * + * It delegates the actual arithmetic work to: + * ecp_precompute_comb() and ecp_mul_comb_with_precomp() + * + * See comments on ecp_comb_recode_core() regarding the computation strategy. + */ +static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_ecp_restart_ctx *rs_ctx ) +{ + int ret; + unsigned char w, p_eq_g, i; + size_t d; + unsigned char T_size, T_ok; + mbedtls_ecp_point *T; + + ECP_RS_ENTER( rsm ); + + /* Is P the base point ? */ +#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 + p_eq_g = ( mbedtls_mpi_cmp_mpi( &P->Y, &grp->G.Y ) == 0 && + mbedtls_mpi_cmp_mpi( &P->X, &grp->G.X ) == 0 ); +#else + p_eq_g = 0; +#endif + + /* Pick window size and deduce related sizes */ + w = ecp_pick_window_size( grp, p_eq_g ); + T_size = 1U << ( w - 1 ); d = ( grp->nbits + w - 1 ) / w; - /* - * Prepare precomputed points: if P == G we want to - * use grp->T if already initialized, or initialize it. - */ - T = p_eq_g ? grp->T : NULL; + /* Pre-computed table: do we have it already for the base point? */ + if( p_eq_g && grp->T != NULL ) + { + /* second pointer to the same table, will be deleted on exit */ + T = grp->T; + T_ok = 1; + } + else +#if defined(MBEDTLS_ECP_RESTARTABLE) + /* Pre-computed table: do we have one in progress? complete? */ + if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->T != NULL ) + { + /* transfer ownership of T from rsm to local function */ + T = rs_ctx->rsm->T; + rs_ctx->rsm->T = NULL; + rs_ctx->rsm->T_size = 0; - if( T == NULL ) + /* This effectively jumps to the call to mul_comb_after_precomp() */ + T_ok = rs_ctx->rsm->state >= ecp_rsm_comb_core; + } + else +#endif + /* Allocate table if we didn't have any */ { - T = mbedtls_calloc( pre_len, sizeof( mbedtls_ecp_point ) ); + T = mbedtls_calloc( T_size, sizeof( mbedtls_ecp_point ) ); if( T == NULL ) { ret = MBEDTLS_ERR_ECP_ALLOC_FAILED; goto cleanup; } - MBEDTLS_MPI_CHK( ecp_precompute_comb( grp, T, P, w, d ) ); + for( i = 0; i < T_size; i++ ) + mbedtls_ecp_point_init( &T[i] ); + + T_ok = 0; + } + + /* Compute table (or finish computing it) if not done already */ + if( !T_ok ) + { + MBEDTLS_MPI_CHK( ecp_precompute_comb( grp, T, P, w, d, rs_ctx ) ); if( p_eq_g ) { + /* almost transfer ownership of T to the group, but keep a copy of + * the pointer to use for calling the next function more easily */ grp->T = T; - grp->T_size = pre_len; + grp->T_size = T_size; } } - /* - * Make sure M is odd (M = m or M = N - m, since N is odd) - * using the fact that m * P = - (N - m) * P - */ - m_is_odd = ( mbedtls_mpi_get_bit( m, 0 ) == 1 ); - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &M, m ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mm, &grp->N, m ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &M, &mm, ! m_is_odd ) ); + /* Actual comb multiplication using precomputed points */ + MBEDTLS_MPI_CHK( ecp_mul_comb_after_precomp( grp, R, m, + T, T_size, w, d, + f_rng, p_rng, rs_ctx ) ); - /* - * Go for comb multiplication, R = M * P - */ - ecp_comb_fixed( k, d, w, &M ); - MBEDTLS_MPI_CHK( ecp_mul_comb_core( grp, R, T, pre_len, k, d, f_rng, p_rng ) ); +cleanup: - /* - * Now get m * P from M * P and normalize it - */ - MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, R, ! m_is_odd ) ); - MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, R ) ); + /* does T belong to the group? */ + if( T == grp->T ) + T = NULL; -cleanup: + /* does T belong to the restart context? */ +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS && T != NULL ) + { + /* transfer ownership of T from local function to rsm */ + rs_ctx->rsm->T_size = T_size; + rs_ctx->rsm->T = T; + T = NULL; + } +#endif - if( T != NULL && ! p_eq_g ) + /* did T belong to us? then let's destroy it! */ + if( T != NULL ) { - for( i = 0; i < pre_len; i++ ) + for( i = 0; i < T_size; i++ ) mbedtls_ecp_point_free( &T[i] ); mbedtls_free( T ); } - mbedtls_mpi_free( &M ); - mbedtls_mpi_free( &mm ); - + /* don't free R while in progress in case R == P */ +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) +#endif + /* prevent caller from using invalid value */ if( ret != 0 ) mbedtls_ecp_point_free( R ); + ECP_RS_LEAVE( rsm ); + return( ret ); } @@ -1482,10 +2135,8 @@ static int ecp_normalize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P int ret; #if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) - if ( mbedtls_internal_ecp_grp_capable( grp ) ) - { - return mbedtls_internal_ecp_normalize_mxz( grp, P ); - } + if( mbedtls_internal_ecp_grp_capable( grp ) ) + return( mbedtls_internal_ecp_normalize_mxz( grp, P ) ); #endif /* MBEDTLS_ECP_NORMALIZE_MXZ_ALT */ MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &P->Z, &P->Z, &grp->P ) ); @@ -1513,10 +2164,8 @@ static int ecp_randomize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P int count = 0; #if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) - if ( mbedtls_internal_ecp_grp_capable( grp ) ) - { - return mbedtls_internal_ecp_randomize_mxz( grp, P, f_rng, p_rng ); - } + if( mbedtls_internal_ecp_grp_capable( grp ) ) + return( mbedtls_internal_ecp_randomize_mxz( grp, P, f_rng, p_rng ); #endif /* MBEDTLS_ECP_RANDOMIZE_MXZ_ALT */ p_size = ( grp->pbits + 7 ) / 8; @@ -1568,10 +2217,8 @@ static int ecp_double_add_mxz( const mbedtls_ecp_group *grp, mbedtls_mpi A, AA, B, BB, E, C, D, DA, CB; #if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) - if ( mbedtls_internal_ecp_grp_capable( grp ) ) - { - return mbedtls_internal_ecp_double_add_mxz( grp, R, S, P, Q, d ); - } + if( mbedtls_internal_ecp_grp_capable( grp ) ) + return( mbedtls_internal_ecp_double_add_mxz( grp, R, S, P, Q, d ) ); #endif /* MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT */ mbedtls_mpi_init( &A ); mbedtls_mpi_init( &AA ); mbedtls_mpi_init( &B ); @@ -1668,54 +2315,85 @@ cleanup: #endif /* ECP_MONTGOMERY */ /* - * Multiplication R = m * P + * Restartable multiplication R = m * P */ -int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, +int mbedtls_ecp_mul_restartable( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, const mbedtls_ecp_point *P, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + mbedtls_ecp_restart_ctx *rs_ctx ) { int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; #if defined(MBEDTLS_ECP_INTERNAL_ALT) char is_grp_capable = 0; #endif - - /* Common sanity checks */ - if( mbedtls_mpi_cmp_int( &P->Z, 1 ) != 0 ) - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - - if( ( ret = mbedtls_ecp_check_privkey( grp, m ) ) != 0 || - ( ret = mbedtls_ecp_check_pubkey( grp, P ) ) != 0 ) - return( ret ); + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( R != NULL ); + ECP_VALIDATE_RET( m != NULL ); + ECP_VALIDATE_RET( P != NULL ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + /* reset ops count for this call if top-level */ + if( rs_ctx != NULL && rs_ctx->depth++ == 0 ) + rs_ctx->ops_done = 0; +#endif #if defined(MBEDTLS_ECP_INTERNAL_ALT) - if ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) ) - { + if( ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) ) ) MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) ); +#endif /* MBEDTLS_ECP_INTERNAL_ALT */ + +#if defined(MBEDTLS_ECP_RESTARTABLE) + /* skip argument check when restarting */ + if( rs_ctx == NULL || rs_ctx->rsm == NULL ) +#endif + { + /* check_privkey is free */ + MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_CHK ); + + /* Common sanity checks */ + MBEDTLS_MPI_CHK( mbedtls_ecp_check_privkey( grp, m ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, P ) ); } -#endif /* MBEDTLS_ECP_INTERNAL_ALT */ + ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; #if defined(ECP_MONTGOMERY) if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY ) - ret = ecp_mul_mxz( grp, R, m, P, f_rng, p_rng ); - + MBEDTLS_MPI_CHK( ecp_mul_mxz( grp, R, m, P, f_rng, p_rng ) ); #endif #if defined(ECP_SHORTWEIERSTRASS) if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS ) - ret = ecp_mul_comb( grp, R, m, P, f_rng, p_rng ); - + MBEDTLS_MPI_CHK( ecp_mul_comb( grp, R, m, P, f_rng, p_rng, rs_ctx ) ); #endif -#if defined(MBEDTLS_ECP_INTERNAL_ALT) + cleanup: - if ( is_grp_capable ) - { +#if defined(MBEDTLS_ECP_INTERNAL_ALT) + if( is_grp_capable ) mbedtls_internal_ecp_free( grp ); - } - #endif /* MBEDTLS_ECP_INTERNAL_ALT */ + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL ) + rs_ctx->depth--; +#endif + return( ret ); } +/* + * Multiplication R = m * P + */ +int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( R != NULL ); + ECP_VALIDATE_RET( m != NULL ); + ECP_VALIDATE_RET( P != NULL ); + return( mbedtls_ecp_mul_restartable( grp, R, m, P, f_rng, p_rng, NULL ) ); +} + #if defined(ECP_SHORTWEIERSTRASS) /* * Check that an affine point is valid as a public key, @@ -1773,7 +2451,8 @@ cleanup: static int mbedtls_ecp_mul_shortcuts( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, - const mbedtls_ecp_point *P ) + const mbedtls_ecp_point *P, + mbedtls_ecp_restart_ctx *rs_ctx ) { int ret; @@ -1789,7 +2468,8 @@ static int mbedtls_ecp_mul_shortcuts( mbedtls_ecp_group *grp, } else { - MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, R, m, P, NULL, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, R, m, P, + NULL, NULL, rs_ctx ) ); } cleanup: @@ -1797,51 +2477,118 @@ cleanup: } /* - * Linear combination + * Restartable linear combination * NOT constant-time */ -int mbedtls_ecp_muladd( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, +int mbedtls_ecp_muladd_restartable( + mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, const mbedtls_ecp_point *P, - const mbedtls_mpi *n, const mbedtls_ecp_point *Q ) + const mbedtls_mpi *n, const mbedtls_ecp_point *Q, + mbedtls_ecp_restart_ctx *rs_ctx ) { int ret; mbedtls_ecp_point mP; + mbedtls_ecp_point *pmP = &mP; + mbedtls_ecp_point *pR = R; #if defined(MBEDTLS_ECP_INTERNAL_ALT) char is_grp_capable = 0; #endif + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( R != NULL ); + ECP_VALIDATE_RET( m != NULL ); + ECP_VALIDATE_RET( P != NULL ); + ECP_VALIDATE_RET( n != NULL ); + ECP_VALIDATE_RET( Q != NULL ); if( ecp_get_type( grp ) != ECP_TYPE_SHORT_WEIERSTRASS ) return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); mbedtls_ecp_point_init( &mP ); - MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, &mP, m, P ) ); - MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, R, n, Q ) ); + ECP_RS_ENTER( ma ); -#if defined(MBEDTLS_ECP_INTERNAL_ALT) - if ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) ) +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->ma != NULL ) { - MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) ); + /* redirect intermediate results to restart context */ + pmP = &rs_ctx->ma->mP; + pR = &rs_ctx->ma->R; + + /* jump to next operation */ + if( rs_ctx->ma->state == ecp_rsma_mul2 ) + goto mul2; + if( rs_ctx->ma->state == ecp_rsma_add ) + goto add; + if( rs_ctx->ma->state == ecp_rsma_norm ) + goto norm; } +#endif /* MBEDTLS_ECP_RESTARTABLE */ + MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, pmP, m, P, rs_ctx ) ); +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->ma != NULL ) + rs_ctx->ma->state = ecp_rsma_mul2; + +mul2: +#endif + MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, pR, n, Q, rs_ctx ) ); + +#if defined(MBEDTLS_ECP_INTERNAL_ALT) + if( ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) ) ) + MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) ); #endif /* MBEDTLS_ECP_INTERNAL_ALT */ - MBEDTLS_MPI_CHK( ecp_add_mixed( grp, R, &mP, R ) ); - MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, R ) ); -cleanup: +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->ma != NULL ) + rs_ctx->ma->state = ecp_rsma_add; + +add: +#endif + MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_ADD ); + MBEDTLS_MPI_CHK( ecp_add_mixed( grp, pR, pmP, pR ) ); +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->ma != NULL ) + rs_ctx->ma->state = ecp_rsma_norm; + +norm: +#endif + MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV ); + MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, pR ) ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->ma != NULL ) + MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, pR ) ); +#endif +cleanup: #if defined(MBEDTLS_ECP_INTERNAL_ALT) - if ( is_grp_capable ) - { + if( is_grp_capable ) mbedtls_internal_ecp_free( grp ); - } - #endif /* MBEDTLS_ECP_INTERNAL_ALT */ + mbedtls_ecp_point_free( &mP ); + ECP_RS_LEAVE( ma ); + return( ret ); } +/* + * Linear combination + * NOT constant-time + */ +int mbedtls_ecp_muladd( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + const mbedtls_mpi *n, const mbedtls_ecp_point *Q ) +{ + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( R != NULL ); + ECP_VALIDATE_RET( m != NULL ); + ECP_VALIDATE_RET( P != NULL ); + ECP_VALIDATE_RET( n != NULL ); + ECP_VALIDATE_RET( Q != NULL ); + return( mbedtls_ecp_muladd_restartable( grp, R, m, P, n, Q, NULL ) ); +} #if defined(ECP_MONTGOMERY) /* @@ -1862,8 +2609,12 @@ static int ecp_check_pubkey_mx( const mbedtls_ecp_group *grp, const mbedtls_ecp_ /* * Check that a point is valid as a public key */ -int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt ) +int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp, + const mbedtls_ecp_point *pt ) { + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( pt != NULL ); + /* Must use affine coordinates */ if( mbedtls_mpi_cmp_int( &pt->Z, 1 ) != 0 ) return( MBEDTLS_ERR_ECP_INVALID_KEY ); @@ -1882,8 +2633,12 @@ int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp, const mbedtls_ecp_po /* * Check that an mbedtls_mpi is valid as a private key */ -int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, const mbedtls_mpi *d ) +int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, + const mbedtls_mpi *d ) { + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( d != NULL ); + #if defined(ECP_MONTGOMERY) if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY ) { @@ -1892,7 +2647,6 @@ int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, const mbedtls_mpi * mbedtls_mpi_get_bit( d, 1 ) != 0 || mbedtls_mpi_bitlen( d ) - 1 != grp->nbits ) /* mbedtls_mpi_bitlen is one-based! */ return( MBEDTLS_ERR_ECP_INVALID_KEY ); - else /* see [Curve25519] page 5 */ if( grp->nbits == 254 && mbedtls_mpi_get_bit( d, 2 ) != 0 ) @@ -1917,16 +2671,21 @@ int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, const mbedtls_mpi * } /* - * Generate a keypair with configurable base point + * Generate a private key */ -int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp, - const mbedtls_ecp_point *G, - mbedtls_mpi *d, mbedtls_ecp_point *Q, +int mbedtls_ecp_gen_privkey( const mbedtls_ecp_group *grp, + mbedtls_mpi *d, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { - int ret; - size_t n_size = ( grp->nbits + 7 ) / 8; + int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + size_t n_size; + + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( d != NULL ); + ECP_VALIDATE_RET( f_rng != NULL ); + + n_size = ( grp->nbits + 7 ) / 8; #if defined(ECP_MONTGOMERY) if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY ) @@ -1954,8 +2713,8 @@ int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp, MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 2, 0 ) ); } } - else #endif /* ECP_MONTGOMERY */ + #if defined(ECP_SHORTWEIERSTRASS) if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS ) { @@ -1989,15 +2748,33 @@ int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp, while( mbedtls_mpi_cmp_int( d, 1 ) < 0 || mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 ); } - else #endif /* ECP_SHORTWEIERSTRASS */ - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); cleanup: - if( ret != 0 ) - return( ret ); + return( ret ); +} - return( mbedtls_ecp_mul( grp, Q, d, G, f_rng, p_rng ) ); +/* + * Generate a keypair with configurable base point + */ +int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp, + const mbedtls_ecp_point *G, + mbedtls_mpi *d, mbedtls_ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( d != NULL ); + ECP_VALIDATE_RET( G != NULL ); + ECP_VALIDATE_RET( Q != NULL ); + ECP_VALIDATE_RET( f_rng != NULL ); + + MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, d, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, Q, d, G, f_rng, p_rng ) ); + +cleanup: + return( ret ); } /* @@ -2008,6 +2785,11 @@ int mbedtls_ecp_gen_keypair( mbedtls_ecp_group *grp, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( d != NULL ); + ECP_VALIDATE_RET( Q != NULL ); + ECP_VALIDATE_RET( f_rng != NULL ); + return( mbedtls_ecp_gen_keypair_base( grp, &grp->G, d, Q, f_rng, p_rng ) ); } @@ -2018,6 +2800,8 @@ int mbedtls_ecp_gen_key( mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { int ret; + ECP_VALIDATE_RET( key != NULL ); + ECP_VALIDATE_RET( f_rng != NULL ); if( ( ret = mbedtls_ecp_group_load( &key->grp, grp_id ) ) != 0 ) return( ret ); @@ -2033,6 +2817,8 @@ int mbedtls_ecp_check_pub_priv( const mbedtls_ecp_keypair *pub, const mbedtls_ec int ret; mbedtls_ecp_point Q; mbedtls_ecp_group grp; + ECP_VALIDATE_RET( pub != NULL ); + ECP_VALIDATE_RET( prv != NULL ); if( pub->grp.id == MBEDTLS_ECP_DP_NONE || pub->grp.id != prv->grp.id || diff --git a/thirdparty/mbedtls/library/ecp_curves.c b/thirdparty/mbedtls/library/ecp_curves.c index 68e2441ae8..731621dc3c 100644 --- a/thirdparty/mbedtls/library/ecp_curves.c +++ b/thirdparty/mbedtls/library/ecp_curves.c @@ -28,11 +28,18 @@ #if defined(MBEDTLS_ECP_C) #include "mbedtls/ecp.h" +#include "mbedtls/platform_util.h" #include <string.h> #if !defined(MBEDTLS_ECP_ALT) +/* Parameter validation macros based on platform_util.h */ +#define ECP_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA ) +#define ECP_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + #if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ !defined(inline) && !defined(__cplusplus) #define inline __inline @@ -746,6 +753,7 @@ cleanup: */ int mbedtls_ecp_group_load( mbedtls_ecp_group *grp, mbedtls_ecp_group_id id ) { + ECP_VALIDATE_RET( grp != NULL ); mbedtls_ecp_group_free( grp ); grp->id = id; diff --git a/thirdparty/mbedtls/library/entropy_poll.c b/thirdparty/mbedtls/library/entropy_poll.c index f44a753f4d..ba56b70f77 100644 --- a/thirdparty/mbedtls/library/entropy_poll.c +++ b/thirdparty/mbedtls/library/entropy_poll.c @@ -114,6 +114,7 @@ int mbedtls_platform_entropy_poll( void *data, unsigned char *output, size_t len #include <sys/syscall.h> #if defined(SYS_getrandom) #define HAVE_GETRANDOM +#include <errno.h> static int getrandom_wrapper( void *buf, size_t buflen, unsigned int flags ) { @@ -123,47 +124,8 @@ static int getrandom_wrapper( void *buf, size_t buflen, unsigned int flags ) memset( buf, 0, buflen ); #endif #endif - return( syscall( SYS_getrandom, buf, buflen, flags ) ); } - -#include <sys/utsname.h> -/* Check if version is at least 3.17.0 */ -static int check_version_3_17_plus( void ) -{ - int minor; - struct utsname un; - const char *ver; - - /* Get version information */ - uname(&un); - ver = un.release; - - /* Check major version; assume a single digit */ - if( ver[0] < '3' || ver[0] > '9' || ver [1] != '.' ) - return( -1 ); - - if( ver[0] - '0' > 3 ) - return( 0 ); - - /* Ok, so now we know major == 3, check minor. - * Assume 1 or 2 digits. */ - if( ver[2] < '0' || ver[2] > '9' ) - return( -1 ); - - minor = ver[2] - '0'; - - if( ver[3] >= '0' && ver[3] <= '9' ) - minor = 10 * minor + ver[3] - '0'; - else if( ver [3] != '.' ) - return( -1 ); - - if( minor < 17 ) - return( -1 ); - - return( 0 ); -} -static int has_getrandom = -1; #endif /* SYS_getrandom */ #endif /* __linux__ */ @@ -174,22 +136,21 @@ int mbedtls_platform_entropy_poll( void *data, { FILE *file; size_t read_len; + int ret; ((void) data); #if defined(HAVE_GETRANDOM) - if( has_getrandom == -1 ) - has_getrandom = ( check_version_3_17_plus() == 0 ); - - if( has_getrandom ) + ret = getrandom_wrapper( output, len, 0 ); + if( ret >= 0 ) { - int ret; - - if( ( ret = getrandom_wrapper( output, len, 0 ) ) < 0 ) - return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); - *olen = ret; return( 0 ); } + else if( errno != ENOSYS ) + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + /* Fall through if the system call isn't known. */ +#else + ((void) ret); #endif /* HAVE_GETRANDOM */ *olen = 0; diff --git a/thirdparty/mbedtls/library/entropy_poll.c.orig b/thirdparty/mbedtls/library/entropy_poll.c.orig deleted file mode 100644 index 040aa117dc..0000000000 --- a/thirdparty/mbedtls/library/entropy_poll.c.orig +++ /dev/null @@ -1,275 +0,0 @@ -/* - * Platform-specific and custom entropy polling functions - * - * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -#if defined(__linux__) -/* Ensure that syscall() is available even when compiling with -std=c99 */ -#define _GNU_SOURCE -#endif - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include <string.h> - -#if defined(MBEDTLS_ENTROPY_C) - -#include "mbedtls/entropy.h" -#include "mbedtls/entropy_poll.h" - -#if defined(MBEDTLS_TIMING_C) -#include "mbedtls/timing.h" -#endif -#if defined(MBEDTLS_HAVEGE_C) -#include "mbedtls/havege.h" -#endif -#if defined(MBEDTLS_ENTROPY_NV_SEED) -#include "mbedtls/platform.h" -#endif - -#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY) - -#if !defined(unix) && !defined(__unix__) && !defined(__unix) && \ - !defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \ - !defined(__HAIKU__) -#error "Platform entropy sources only work on Unix and Windows, see MBEDTLS_NO_PLATFORM_ENTROPY in config.h" -#endif - -#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) - -#if !defined(_WIN32_WINNT) -#define _WIN32_WINNT 0x0400 -#endif -#include <windows.h> -#include <wincrypt.h> - -int mbedtls_platform_entropy_poll( void *data, unsigned char *output, size_t len, - size_t *olen ) -{ - HCRYPTPROV provider; - ((void) data); - *olen = 0; - - if( CryptAcquireContext( &provider, NULL, NULL, - PROV_RSA_FULL, CRYPT_VERIFYCONTEXT ) == FALSE ) - { - return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); - } - - if( CryptGenRandom( provider, (DWORD) len, output ) == FALSE ) - { - CryptReleaseContext( provider, 0 ); - return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); - } - - CryptReleaseContext( provider, 0 ); - *olen = len; - - return( 0 ); -} -#else /* _WIN32 && !EFIX64 && !EFI32 */ - -/* - * Test for Linux getrandom() support. - * Since there is no wrapper in the libc yet, use the generic syscall wrapper - * available in GNU libc and compatible libc's (eg uClibc). - */ -#if defined(__linux__) && defined(__GLIBC__) -#include <unistd.h> -#include <sys/syscall.h> -#if defined(SYS_getrandom) -#define HAVE_GETRANDOM - -static int getrandom_wrapper( void *buf, size_t buflen, unsigned int flags ) -{ - /* MemSan cannot understand that the syscall writes to the buffer */ -#if defined(__has_feature) -#if __has_feature(memory_sanitizer) - memset( buf, 0, buflen ); -#endif -#endif - - return( syscall( SYS_getrandom, buf, buflen, flags ) ); -} - -#include <sys/utsname.h> -/* Check if version is at least 3.17.0 */ -static int check_version_3_17_plus( void ) -{ - int minor; - struct utsname un; - const char *ver; - - /* Get version information */ - uname(&un); - ver = un.release; - - /* Check major version; assume a single digit */ - if( ver[0] < '3' || ver[0] > '9' || ver [1] != '.' ) - return( -1 ); - - if( ver[0] - '0' > 3 ) - return( 0 ); - - /* Ok, so now we know major == 3, check minor. - * Assume 1 or 2 digits. */ - if( ver[2] < '0' || ver[2] > '9' ) - return( -1 ); - - minor = ver[2] - '0'; - - if( ver[3] >= '0' && ver[3] <= '9' ) - minor = 10 * minor + ver[3] - '0'; - else if( ver [3] != '.' ) - return( -1 ); - - if( minor < 17 ) - return( -1 ); - - return( 0 ); -} -static int has_getrandom = -1; -#endif /* SYS_getrandom */ -#endif /* __linux__ */ - -#include <stdio.h> - -int mbedtls_platform_entropy_poll( void *data, - unsigned char *output, size_t len, size_t *olen ) -{ - FILE *file; - size_t read_len; - ((void) data); - -#if defined(HAVE_GETRANDOM) - if( has_getrandom == -1 ) - has_getrandom = ( check_version_3_17_plus() == 0 ); - - if( has_getrandom ) - { - int ret; - - if( ( ret = getrandom_wrapper( output, len, 0 ) ) < 0 ) - return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); - - *olen = ret; - return( 0 ); - } -#endif /* HAVE_GETRANDOM */ - - *olen = 0; - - file = fopen( "/dev/urandom", "rb" ); - if( file == NULL ) - return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); - - read_len = fread( output, 1, len, file ); - if( read_len != len ) - { - fclose( file ); - return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); - } - - fclose( file ); - *olen = len; - - return( 0 ); -} -#endif /* _WIN32 && !EFIX64 && !EFI32 */ -#endif /* !MBEDTLS_NO_PLATFORM_ENTROPY */ - -#if defined(MBEDTLS_TEST_NULL_ENTROPY) -int mbedtls_null_entropy_poll( void *data, - unsigned char *output, size_t len, size_t *olen ) -{ - ((void) data); - ((void) output); - *olen = 0; - - if( len < sizeof(unsigned char) ) - return( 0 ); - - *olen = sizeof(unsigned char); - - return( 0 ); -} -#endif - -#if defined(MBEDTLS_TIMING_C) -int mbedtls_hardclock_poll( void *data, - unsigned char *output, size_t len, size_t *olen ) -{ - unsigned long timer = mbedtls_timing_hardclock(); - ((void) data); - *olen = 0; - - if( len < sizeof(unsigned long) ) - return( 0 ); - - memcpy( output, &timer, sizeof(unsigned long) ); - *olen = sizeof(unsigned long); - - return( 0 ); -} -#endif /* MBEDTLS_TIMING_C */ - -#if defined(MBEDTLS_HAVEGE_C) -int mbedtls_havege_poll( void *data, - unsigned char *output, size_t len, size_t *olen ) -{ - mbedtls_havege_state *hs = (mbedtls_havege_state *) data; - *olen = 0; - - if( mbedtls_havege_random( hs, output, len ) != 0 ) - return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); - - *olen = len; - - return( 0 ); -} -#endif /* MBEDTLS_HAVEGE_C */ - -#if defined(MBEDTLS_ENTROPY_NV_SEED) -int mbedtls_nv_seed_poll( void *data, - unsigned char *output, size_t len, size_t *olen ) -{ - unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; - size_t use_len = MBEDTLS_ENTROPY_BLOCK_SIZE; - ((void) data); - - memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE ); - - if( mbedtls_nv_seed_read( buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) < 0 ) - return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); - - if( len < use_len ) - use_len = len; - - memcpy( output, buf, use_len ); - *olen = use_len; - - return( 0 ); -} -#endif /* MBEDTLS_ENTROPY_NV_SEED */ - -#endif /* MBEDTLS_ENTROPY_C */ diff --git a/thirdparty/mbedtls/library/error.c b/thirdparty/mbedtls/library/error.c index 774244b454..12312a0562 100644 --- a/thirdparty/mbedtls/library/error.c +++ b/thirdparty/mbedtls/library/error.c @@ -165,6 +165,10 @@ #include "mbedtls/pkcs5.h" #endif +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#endif + #if defined(MBEDTLS_POLY1305_C) #include "mbedtls/poly1305.h" #endif @@ -289,6 +293,8 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen ) mbedtls_snprintf( buf, buflen, "ECP - The buffer contains a valid signature followed by more data" ); if( use_ret == -(MBEDTLS_ERR_ECP_HW_ACCEL_FAILED) ) mbedtls_snprintf( buf, buflen, "ECP - The ECP hardware accelerator failed" ); + if( use_ret == -(MBEDTLS_ERR_ECP_IN_PROGRESS) ) + mbedtls_snprintf( buf, buflen, "ECP - Operation in progress, call again with the same parameters to continue" ); #endif /* MBEDTLS_ECP_C */ #if defined(MBEDTLS_MD_C) @@ -515,6 +521,10 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen ) mbedtls_snprintf( buf, buflen, "SSL - Internal-only message signaling that further message-processing should be done" ); if( use_ret == -(MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS) ) mbedtls_snprintf( buf, buflen, "SSL - The asynchronous operation is not completed yet" ); + if( use_ret == -(MBEDTLS_ERR_SSL_EARLY_MESSAGE) ) + mbedtls_snprintf( buf, buflen, "SSL - Internal-only message signaling that a message arrived early" ); + if( use_ret == -(MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS) ) + mbedtls_snprintf( buf, buflen, "SSL - A cryptographic operation is in progress. Try again later" ); #endif /* MBEDTLS_SSL_TLS_C */ #if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) @@ -608,8 +618,8 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen ) #endif /* MBEDTLS_ARC4_C */ #if defined(MBEDTLS_ARIA_C) - if( use_ret == -(MBEDTLS_ERR_ARIA_INVALID_KEY_LENGTH) ) - mbedtls_snprintf( buf, buflen, "ARIA - Invalid key length" ); + if( use_ret == -(MBEDTLS_ERR_ARIA_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "ARIA - Bad input data" ); if( use_ret == -(MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH) ) mbedtls_snprintf( buf, buflen, "ARIA - Invalid data input length" ); if( use_ret == -(MBEDTLS_ERR_ARIA_FEATURE_UNAVAILABLE) ) @@ -662,17 +672,17 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen ) #endif /* MBEDTLS_BIGNUM_C */ #if defined(MBEDTLS_BLOWFISH_C) - if( use_ret == -(MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH) ) - mbedtls_snprintf( buf, buflen, "BLOWFISH - Invalid key length" ); - if( use_ret == -(MBEDTLS_ERR_BLOWFISH_HW_ACCEL_FAILED) ) - mbedtls_snprintf( buf, buflen, "BLOWFISH - Blowfish hardware accelerator failed" ); + if( use_ret == -(MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "BLOWFISH - Bad input data" ); if( use_ret == -(MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH) ) mbedtls_snprintf( buf, buflen, "BLOWFISH - Invalid data input length" ); + if( use_ret == -(MBEDTLS_ERR_BLOWFISH_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "BLOWFISH - Blowfish hardware accelerator failed" ); #endif /* MBEDTLS_BLOWFISH_C */ #if defined(MBEDTLS_CAMELLIA_C) - if( use_ret == -(MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH) ) - mbedtls_snprintf( buf, buflen, "CAMELLIA - Invalid key length" ); + if( use_ret == -(MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "CAMELLIA - Bad input data" ); if( use_ret == -(MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH) ) mbedtls_snprintf( buf, buflen, "CAMELLIA - Invalid data input length" ); if( use_ret == -(MBEDTLS_ERR_CAMELLIA_HW_ACCEL_FAILED) ) @@ -821,6 +831,13 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen ) mbedtls_snprintf( buf, buflen, "PADLOCK - Input data should be aligned" ); #endif /* MBEDTLS_PADLOCK_C */ +#if defined(MBEDTLS_PLATFORM_C) + if( use_ret == -(MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "PLATFORM - Hardware accelerator failed" ); + if( use_ret == -(MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED) ) + mbedtls_snprintf( buf, buflen, "PLATFORM - The requested feature is not supported by the platform" ); +#endif /* MBEDTLS_PLATFORM_C */ + #if defined(MBEDTLS_POLY1305_C) if( use_ret == -(MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA) ) mbedtls_snprintf( buf, buflen, "POLY1305 - Invalid input parameter(s)" ); @@ -838,16 +855,22 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen ) #if defined(MBEDTLS_SHA1_C) if( use_ret == -(MBEDTLS_ERR_SHA1_HW_ACCEL_FAILED) ) mbedtls_snprintf( buf, buflen, "SHA1 - SHA-1 hardware accelerator failed" ); + if( use_ret == -(MBEDTLS_ERR_SHA1_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "SHA1 - SHA-1 input data was malformed" ); #endif /* MBEDTLS_SHA1_C */ #if defined(MBEDTLS_SHA256_C) if( use_ret == -(MBEDTLS_ERR_SHA256_HW_ACCEL_FAILED) ) mbedtls_snprintf( buf, buflen, "SHA256 - SHA-256 hardware accelerator failed" ); + if( use_ret == -(MBEDTLS_ERR_SHA256_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "SHA256 - SHA-256 input data was malformed" ); #endif /* MBEDTLS_SHA256_C */ #if defined(MBEDTLS_SHA512_C) if( use_ret == -(MBEDTLS_ERR_SHA512_HW_ACCEL_FAILED) ) mbedtls_snprintf( buf, buflen, "SHA512 - SHA-512 hardware accelerator failed" ); + if( use_ret == -(MBEDTLS_ERR_SHA512_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "SHA512 - SHA-512 input data was malformed" ); #endif /* MBEDTLS_SHA512_C */ #if defined(MBEDTLS_THREADING_C) diff --git a/thirdparty/mbedtls/library/gcm.c b/thirdparty/mbedtls/library/gcm.c index 57b027933d..675926a518 100644 --- a/thirdparty/mbedtls/library/gcm.c +++ b/thirdparty/mbedtls/library/gcm.c @@ -48,9 +48,8 @@ #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) #include "mbedtls/aes.h" -#if defined(MBEDTLS_PLATFORM_C) #include "mbedtls/platform.h" -#else +#if !defined(MBEDTLS_PLATFORM_C) #include <stdio.h> #define mbedtls_printf printf #endif /* MBEDTLS_PLATFORM_C */ @@ -58,6 +57,12 @@ #if !defined(MBEDTLS_GCM_ALT) +/* Parameter validation macros */ +#define GCM_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_GCM_BAD_INPUT ) +#define GCM_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + /* * 32-bit integer manipulation macros (big endian) */ @@ -86,6 +91,7 @@ */ void mbedtls_gcm_init( mbedtls_gcm_context *ctx ) { + GCM_VALIDATE( ctx != NULL ); memset( ctx, 0, sizeof( mbedtls_gcm_context ) ); } @@ -165,6 +171,10 @@ int mbedtls_gcm_setkey( mbedtls_gcm_context *ctx, int ret; const mbedtls_cipher_info_t *cipher_info; + GCM_VALIDATE_RET( ctx != NULL ); + GCM_VALIDATE_RET( key != NULL ); + GCM_VALIDATE_RET( keybits == 128 || keybits == 192 || keybits == 256 ); + cipher_info = mbedtls_cipher_info_from_values( cipher, keybits, MBEDTLS_MODE_ECB ); if( cipher_info == NULL ) return( MBEDTLS_ERR_GCM_BAD_INPUT ); @@ -275,6 +285,10 @@ int mbedtls_gcm_starts( mbedtls_gcm_context *ctx, const unsigned char *p; size_t use_len, olen = 0; + GCM_VALIDATE_RET( ctx != NULL ); + GCM_VALIDATE_RET( iv != NULL ); + GCM_VALIDATE_RET( add_len == 0 || add != NULL ); + /* IV and AD are limited to 2^64 bits, so 2^61 bytes */ /* IV is not allowed to be zero length */ if( iv_len == 0 || @@ -357,6 +371,10 @@ int mbedtls_gcm_update( mbedtls_gcm_context *ctx, unsigned char *out_p = output; size_t use_len, olen = 0; + GCM_VALIDATE_RET( ctx != NULL ); + GCM_VALIDATE_RET( length == 0 || input != NULL ); + GCM_VALIDATE_RET( length == 0 || output != NULL ); + if( output > input && (size_t) ( output - input ) < length ) return( MBEDTLS_ERR_GCM_BAD_INPUT ); @@ -410,8 +428,14 @@ int mbedtls_gcm_finish( mbedtls_gcm_context *ctx, { unsigned char work_buf[16]; size_t i; - uint64_t orig_len = ctx->len * 8; - uint64_t orig_add_len = ctx->add_len * 8; + uint64_t orig_len; + uint64_t orig_add_len; + + GCM_VALIDATE_RET( ctx != NULL ); + GCM_VALIDATE_RET( tag != NULL ); + + orig_len = ctx->len * 8; + orig_add_len = ctx->add_len * 8; if( tag_len > 16 || tag_len < 4 ) return( MBEDTLS_ERR_GCM_BAD_INPUT ); @@ -453,6 +477,13 @@ int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_context *ctx, { int ret; + GCM_VALIDATE_RET( ctx != NULL ); + GCM_VALIDATE_RET( iv != NULL ); + GCM_VALIDATE_RET( add_len == 0 || add != NULL ); + GCM_VALIDATE_RET( length == 0 || input != NULL ); + GCM_VALIDATE_RET( length == 0 || output != NULL ); + GCM_VALIDATE_RET( tag != NULL ); + if( ( ret = mbedtls_gcm_starts( ctx, mode, iv, iv_len, add, add_len ) ) != 0 ) return( ret ); @@ -481,6 +512,13 @@ int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx, size_t i; int diff; + GCM_VALIDATE_RET( ctx != NULL ); + GCM_VALIDATE_RET( iv != NULL ); + GCM_VALIDATE_RET( add_len == 0 || add != NULL ); + GCM_VALIDATE_RET( tag != NULL ); + GCM_VALIDATE_RET( length == 0 || input != NULL ); + GCM_VALIDATE_RET( length == 0 || output != NULL ); + if( ( ret = mbedtls_gcm_crypt_and_tag( ctx, MBEDTLS_GCM_DECRYPT, length, iv, iv_len, add, add_len, input, output, tag_len, check_tag ) ) != 0 ) @@ -503,6 +541,8 @@ int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx, void mbedtls_gcm_free( mbedtls_gcm_context *ctx ) { + if( ctx == NULL ) + return; mbedtls_cipher_free( &ctx->cipher_ctx ); mbedtls_platform_zeroize( ctx, sizeof( mbedtls_gcm_context ) ); } @@ -764,7 +804,7 @@ int mbedtls_gcm_self_test( int verbose ) * there is an alternative underlying implementation i.e. when * MBEDTLS_AES_ALT is defined. */ - if( ret == MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE && key_len == 192 ) + if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && key_len == 192 ) { mbedtls_printf( "skipped\n" ); break; diff --git a/thirdparty/mbedtls/library/hmac_drbg.c b/thirdparty/mbedtls/library/hmac_drbg.c index dad55ff861..c50330e7d8 100644 --- a/thirdparty/mbedtls/library/hmac_drbg.c +++ b/thirdparty/mbedtls/library/hmac_drbg.c @@ -66,31 +66,60 @@ void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx ) /* * HMAC_DRBG update, using optional additional data (10.1.2.2) */ -void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx, - const unsigned char *additional, size_t add_len ) +int mbedtls_hmac_drbg_update_ret( mbedtls_hmac_drbg_context *ctx, + const unsigned char *additional, + size_t add_len ) { size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info ); unsigned char rounds = ( additional != NULL && add_len != 0 ) ? 2 : 1; unsigned char sep[1]; unsigned char K[MBEDTLS_MD_MAX_SIZE]; + int ret; for( sep[0] = 0; sep[0] < rounds; sep[0]++ ) { /* Step 1 or 4 */ - mbedtls_md_hmac_reset( &ctx->md_ctx ); - mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len ); - mbedtls_md_hmac_update( &ctx->md_ctx, sep, 1 ); + if( ( ret = mbedtls_md_hmac_reset( &ctx->md_ctx ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx, + ctx->V, md_len ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx, + sep, 1 ) ) != 0 ) + goto exit; if( rounds == 2 ) - mbedtls_md_hmac_update( &ctx->md_ctx, additional, add_len ); - mbedtls_md_hmac_finish( &ctx->md_ctx, K ); + { + if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx, + additional, add_len ) ) != 0 ) + goto exit; + } + if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, K ) ) != 0 ) + goto exit; /* Step 2 or 5 */ - mbedtls_md_hmac_starts( &ctx->md_ctx, K, md_len ); - mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len ); - mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ); + if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, K, md_len ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx, + ctx->V, md_len ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ) ) != 0 ) + goto exit; } + +exit: + mbedtls_platform_zeroize( K, sizeof( K ) ); + return( ret ); } +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx, + const unsigned char *additional, + size_t add_len ) +{ + (void) mbedtls_hmac_drbg_update_ret( ctx, additional, add_len ); +} +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + /* * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA) */ @@ -108,10 +137,13 @@ int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx, * Use the V memory location, which is currently all 0, to initialize the * MD context with an all-zero key. Then set V to its initial value. */ - mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, mbedtls_md_get_size( md_info ) ); + if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, + mbedtls_md_get_size( md_info ) ) ) != 0 ) + return( ret ); memset( ctx->V, 0x01, mbedtls_md_get_size( md_info ) ); - mbedtls_hmac_drbg_update( ctx, data, data_len ); + if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, data, data_len ) ) != 0 ) + return( ret ); return( 0 ); } @@ -124,6 +156,7 @@ int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx, { unsigned char seed[MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT]; size_t seedlen; + int ret; /* III. Check input length */ if( len > MBEDTLS_HMAC_DRBG_MAX_INPUT || @@ -135,7 +168,8 @@ int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx, memset( seed, 0, MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT ); /* IV. Gather entropy_len bytes of entropy for the seed */ - if( ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) != 0 ) + if( ( ret = ctx->f_entropy( ctx->p_entropy, + seed, ctx->entropy_len ) ) != 0 ) return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED ); seedlen = ctx->entropy_len; @@ -148,13 +182,16 @@ int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx, } /* 2. Update state */ - mbedtls_hmac_drbg_update( ctx, seed, seedlen ); + if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, seed, seedlen ) ) != 0 ) + goto exit; /* 3. Reset reseed_counter */ ctx->reseed_counter = 1; +exit: /* 4. Done */ - return( 0 ); + mbedtls_platform_zeroize( seed, seedlen ); + return( ret ); } /* @@ -180,7 +217,8 @@ int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx, * Use the V memory location, which is currently all 0, to initialize the * MD context with an all-zero key. Then set V to its initial value. */ - mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, md_size ); + if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, md_size ) ) != 0 ) + return( ret ); memset( ctx->V, 0x01, md_size ); ctx->f_entropy = f_entropy; @@ -273,16 +311,24 @@ int mbedtls_hmac_drbg_random_with_add( void *p_rng, /* 2. Use additional data if any */ if( additional != NULL && add_len != 0 ) - mbedtls_hmac_drbg_update( ctx, additional, add_len ); + { + if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, + additional, add_len ) ) != 0 ) + goto exit; + } /* 3, 4, 5. Generate bytes */ while( left != 0 ) { size_t use_len = left > md_len ? md_len : left; - mbedtls_md_hmac_reset( &ctx->md_ctx ); - mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len ); - mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ); + if( ( ret = mbedtls_md_hmac_reset( &ctx->md_ctx ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx, + ctx->V, md_len ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ) ) != 0 ) + goto exit; memcpy( out, ctx->V, use_len ); out += use_len; @@ -290,13 +336,16 @@ int mbedtls_hmac_drbg_random_with_add( void *p_rng, } /* 6. Update */ - mbedtls_hmac_drbg_update( ctx, additional, add_len ); + if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, + additional, add_len ) ) != 0 ) + goto exit; /* 7. Update reseed counter */ ctx->reseed_counter++; +exit: /* 8. Done */ - return( 0 ); + return( ret ); } /* @@ -368,35 +417,36 @@ exit: int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path ) { int ret = 0; - FILE *f; + FILE *f = NULL; size_t n; unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ]; + unsigned char c; if( ( f = fopen( path, "rb" ) ) == NULL ) return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR ); - fseek( f, 0, SEEK_END ); - n = (size_t) ftell( f ); - fseek( f, 0, SEEK_SET ); - - if( n > MBEDTLS_HMAC_DRBG_MAX_INPUT ) + n = fread( buf, 1, sizeof( buf ), f ); + if( fread( &c, 1, 1, f ) != 0 ) { - fclose( f ); - return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG ); + ret = MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG; + goto exit; } - - if( fread( buf, 1, n, f ) != n ) + if( n == 0 || ferror( f ) ) + { ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR; - else - mbedtls_hmac_drbg_update( ctx, buf, n ); - + goto exit; + } fclose( f ); + f = NULL; - mbedtls_platform_zeroize( buf, sizeof( buf ) ); + ret = mbedtls_hmac_drbg_update_ret( ctx, buf, n ); +exit: + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + if( f != NULL ) + fclose( f ); if( ret != 0 ) return( ret ); - return( mbedtls_hmac_drbg_write_seed_file( ctx, path ) ); } #endif /* MBEDTLS_FS_IO */ diff --git a/thirdparty/mbedtls/library/nist_kw.c b/thirdparty/mbedtls/library/nist_kw.c index 176af9fe08..317a2426ae 100644 --- a/thirdparty/mbedtls/library/nist_kw.c +++ b/thirdparty/mbedtls/library/nist_kw.c @@ -311,7 +311,7 @@ cleanup: } mbedtls_platform_zeroize( inbuff, KW_SEMIBLOCK_LENGTH * 2 ); mbedtls_platform_zeroize( outbuff, KW_SEMIBLOCK_LENGTH * 2 ); - mbedtls_cipher_finish( &ctx->cipher_ctx, NULL, &olen ); + return( ret ); } @@ -528,7 +528,7 @@ cleanup: mbedtls_platform_zeroize( &bad_padding, sizeof( bad_padding) ); mbedtls_platform_zeroize( &diff, sizeof( diff ) ); mbedtls_platform_zeroize( A, sizeof( A ) ); - mbedtls_cipher_finish( &ctx->cipher_ctx, NULL, &olen ); + return( ret ); } diff --git a/thirdparty/mbedtls/library/pem.c b/thirdparty/mbedtls/library/pem.c index 6069a23dec..897c8a0d6f 100644 --- a/thirdparty/mbedtls/library/pem.c +++ b/thirdparty/mbedtls/library/pem.c @@ -423,9 +423,11 @@ int mbedtls_pem_read_buffer( mbedtls_pem_context *ctx, const char *header, const void mbedtls_pem_free( mbedtls_pem_context *ctx ) { - if( ctx->buf != NULL ) + if ( ctx->buf != NULL ) + { mbedtls_platform_zeroize( ctx->buf, ctx->buflen ); - mbedtls_free( ctx->buf ); + mbedtls_free( ctx->buf ); + } mbedtls_free( ctx->info ); mbedtls_platform_zeroize( ctx, sizeof( mbedtls_pem_context ) ); diff --git a/thirdparty/mbedtls/library/pk.c b/thirdparty/mbedtls/library/pk.c index f05b139e3f..bac685dc19 100644 --- a/thirdparty/mbedtls/library/pk.c +++ b/thirdparty/mbedtls/library/pk.c @@ -44,13 +44,18 @@ #include <limits.h> #include <stdint.h> +/* Parameter validation macros based on platform_util.h */ +#define PK_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_PK_BAD_INPUT_DATA ) +#define PK_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + /* * Initialise a mbedtls_pk_context */ void mbedtls_pk_init( mbedtls_pk_context *ctx ) { - if( ctx == NULL ) - return; + PK_VALIDATE( ctx != NULL ); ctx->pk_info = NULL; ctx->pk_ctx = NULL; @@ -61,14 +66,44 @@ void mbedtls_pk_init( mbedtls_pk_context *ctx ) */ void mbedtls_pk_free( mbedtls_pk_context *ctx ) { - if( ctx == NULL || ctx->pk_info == NULL ) + if( ctx == NULL ) return; - ctx->pk_info->ctx_free_func( ctx->pk_ctx ); + if ( ctx->pk_info != NULL ) + ctx->pk_info->ctx_free_func( ctx->pk_ctx ); mbedtls_platform_zeroize( ctx, sizeof( mbedtls_pk_context ) ); } +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +/* + * Initialize a restart context + */ +void mbedtls_pk_restart_init( mbedtls_pk_restart_ctx *ctx ) +{ + PK_VALIDATE( ctx != NULL ); + ctx->pk_info = NULL; + ctx->rs_ctx = NULL; +} + +/* + * Free the components of a restart context + */ +void mbedtls_pk_restart_free( mbedtls_pk_restart_ctx *ctx ) +{ + if( ctx == NULL || ctx->pk_info == NULL || + ctx->pk_info->rs_free_func == NULL ) + { + return; + } + + ctx->pk_info->rs_free_func( ctx->rs_ctx ); + + ctx->pk_info = NULL; + ctx->rs_ctx = NULL; +} +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + /* * Get pk_info structure from type */ @@ -100,7 +135,8 @@ const mbedtls_pk_info_t * mbedtls_pk_info_from_type( mbedtls_pk_type_t pk_type ) */ int mbedtls_pk_setup( mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info ) { - if( ctx == NULL || info == NULL || ctx->pk_info != NULL ) + PK_VALIDATE_RET( ctx != NULL ); + if( info == NULL || ctx->pk_info != NULL ) return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); if( ( ctx->pk_ctx = info->ctx_alloc_func() ) == NULL ) @@ -123,7 +159,8 @@ int mbedtls_pk_setup_rsa_alt( mbedtls_pk_context *ctx, void * key, mbedtls_rsa_alt_context *rsa_alt; const mbedtls_pk_info_t *info = &mbedtls_rsa_alt_info; - if( ctx == NULL || ctx->pk_info != NULL ) + PK_VALIDATE_RET( ctx != NULL ); + if( ctx->pk_info != NULL ) return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); if( ( ctx->pk_ctx = info->ctx_alloc_func() ) == NULL ) @@ -147,7 +184,9 @@ int mbedtls_pk_setup_rsa_alt( mbedtls_pk_context *ctx, void * key, */ int mbedtls_pk_can_do( const mbedtls_pk_context *ctx, mbedtls_pk_type_t type ) { - /* null or NONE context can't do anything */ + /* A context with null pk_info is not set up yet and can't do anything. + * For backward compatibility, also accept NULL instead of a context + * pointer. */ if( ctx == NULL || ctx->pk_info == NULL ) return( 0 ); @@ -171,17 +210,71 @@ static inline int pk_hashlen_helper( mbedtls_md_type_t md_alg, size_t *hash_len return( 0 ); } +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) /* - * Verify a signature + * Helper to set up a restart context if needed */ -int mbedtls_pk_verify( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, +static int pk_restart_setup( mbedtls_pk_restart_ctx *ctx, + const mbedtls_pk_info_t *info ) +{ + /* Don't do anything if already set up or invalid */ + if( ctx == NULL || ctx->pk_info != NULL ) + return( 0 ); + + /* Should never happen when we're called */ + if( info->rs_alloc_func == NULL || info->rs_free_func == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + if( ( ctx->rs_ctx = info->rs_alloc_func() ) == NULL ) + return( MBEDTLS_ERR_PK_ALLOC_FAILED ); + + ctx->pk_info = info; + + return( 0 ); +} +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + +/* + * Verify a signature (restartable) + */ +int mbedtls_pk_verify_restartable( mbedtls_pk_context *ctx, + mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, - const unsigned char *sig, size_t sig_len ) + const unsigned char *sig, size_t sig_len, + mbedtls_pk_restart_ctx *rs_ctx ) { - if( ctx == NULL || ctx->pk_info == NULL || + PK_VALIDATE_RET( ctx != NULL ); + PK_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && hash_len == 0 ) || + hash != NULL ); + PK_VALIDATE_RET( sig != NULL ); + + if( ctx->pk_info == NULL || pk_hashlen_helper( md_alg, &hash_len ) != 0 ) return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + /* optimization: use non-restartable version if restart disabled */ + if( rs_ctx != NULL && + mbedtls_ecp_restart_is_enabled() && + ctx->pk_info->verify_rs_func != NULL ) + { + int ret; + + if( ( ret = pk_restart_setup( rs_ctx, ctx->pk_info ) ) != 0 ) + return( ret ); + + ret = ctx->pk_info->verify_rs_func( ctx->pk_ctx, + md_alg, hash, hash_len, sig, sig_len, rs_ctx->rs_ctx ); + + if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) + mbedtls_pk_restart_free( rs_ctx ); + + return( ret ); + } +#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + (void) rs_ctx; +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + if( ctx->pk_info->verify_func == NULL ) return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); @@ -190,6 +283,17 @@ int mbedtls_pk_verify( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, } /* + * Verify a signature + */ +int mbedtls_pk_verify( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ) +{ + return( mbedtls_pk_verify_restartable( ctx, md_alg, hash, hash_len, + sig, sig_len, NULL ) ); +} + +/* * Verify a signature with options */ int mbedtls_pk_verify_ext( mbedtls_pk_type_t type, const void *options, @@ -197,7 +301,12 @@ int mbedtls_pk_verify_ext( mbedtls_pk_type_t type, const void *options, const unsigned char *hash, size_t hash_len, const unsigned char *sig, size_t sig_len ) { - if( ctx == NULL || ctx->pk_info == NULL ) + PK_VALIDATE_RET( ctx != NULL ); + PK_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && hash_len == 0 ) || + hash != NULL ); + PK_VALIDATE_RET( sig != NULL ); + + if( ctx->pk_info == NULL ) return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); if( ! mbedtls_pk_can_do( ctx, type ) ) @@ -248,17 +357,47 @@ int mbedtls_pk_verify_ext( mbedtls_pk_type_t type, const void *options, } /* - * Make a signature + * Make a signature (restartable) */ -int mbedtls_pk_sign( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, +int mbedtls_pk_sign_restartable( mbedtls_pk_context *ctx, + mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, unsigned char *sig, size_t *sig_len, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + mbedtls_pk_restart_ctx *rs_ctx ) { - if( ctx == NULL || ctx->pk_info == NULL || + PK_VALIDATE_RET( ctx != NULL ); + PK_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && hash_len == 0 ) || + hash != NULL ); + PK_VALIDATE_RET( sig != NULL ); + + if( ctx->pk_info == NULL || pk_hashlen_helper( md_alg, &hash_len ) != 0 ) return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + /* optimization: use non-restartable version if restart disabled */ + if( rs_ctx != NULL && + mbedtls_ecp_restart_is_enabled() && + ctx->pk_info->sign_rs_func != NULL ) + { + int ret; + + if( ( ret = pk_restart_setup( rs_ctx, ctx->pk_info ) ) != 0 ) + return( ret ); + + ret = ctx->pk_info->sign_rs_func( ctx->pk_ctx, md_alg, + hash, hash_len, sig, sig_len, f_rng, p_rng, rs_ctx->rs_ctx ); + + if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) + mbedtls_pk_restart_free( rs_ctx ); + + return( ret ); + } +#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + (void) rs_ctx; +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + if( ctx->pk_info->sign_func == NULL ) return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); @@ -267,6 +406,18 @@ int mbedtls_pk_sign( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, } /* + * Make a signature + */ +int mbedtls_pk_sign( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + return( mbedtls_pk_sign_restartable( ctx, md_alg, hash, hash_len, + sig, sig_len, f_rng, p_rng, NULL ) ); +} + +/* * Decrypt message */ int mbedtls_pk_decrypt( mbedtls_pk_context *ctx, @@ -274,7 +425,12 @@ int mbedtls_pk_decrypt( mbedtls_pk_context *ctx, unsigned char *output, size_t *olen, size_t osize, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { - if( ctx == NULL || ctx->pk_info == NULL ) + PK_VALIDATE_RET( ctx != NULL ); + PK_VALIDATE_RET( input != NULL || ilen == 0 ); + PK_VALIDATE_RET( output != NULL || osize == 0 ); + PK_VALIDATE_RET( olen != NULL ); + + if( ctx->pk_info == NULL ) return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); if( ctx->pk_info->decrypt_func == NULL ) @@ -292,7 +448,12 @@ int mbedtls_pk_encrypt( mbedtls_pk_context *ctx, unsigned char *output, size_t *olen, size_t osize, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { - if( ctx == NULL || ctx->pk_info == NULL ) + PK_VALIDATE_RET( ctx != NULL ); + PK_VALIDATE_RET( input != NULL || ilen == 0 ); + PK_VALIDATE_RET( output != NULL || osize == 0 ); + PK_VALIDATE_RET( olen != NULL ); + + if( ctx->pk_info == NULL ) return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); if( ctx->pk_info->encrypt_func == NULL ) @@ -307,8 +468,11 @@ int mbedtls_pk_encrypt( mbedtls_pk_context *ctx, */ int mbedtls_pk_check_pair( const mbedtls_pk_context *pub, const mbedtls_pk_context *prv ) { - if( pub == NULL || pub->pk_info == NULL || - prv == NULL || prv->pk_info == NULL || + PK_VALIDATE_RET( pub != NULL ); + PK_VALIDATE_RET( prv != NULL ); + + if( pub->pk_info == NULL || + prv->pk_info == NULL || prv->pk_info->check_pair_func == NULL ) { return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); @@ -333,6 +497,8 @@ int mbedtls_pk_check_pair( const mbedtls_pk_context *pub, const mbedtls_pk_conte */ size_t mbedtls_pk_get_bitlen( const mbedtls_pk_context *ctx ) { + /* For backward compatibility, accept NULL or a context that + * isn't set up yet, and return a fake value that should be safe. */ if( ctx == NULL || ctx->pk_info == NULL ) return( 0 ); @@ -344,7 +510,8 @@ size_t mbedtls_pk_get_bitlen( const mbedtls_pk_context *ctx ) */ int mbedtls_pk_debug( const mbedtls_pk_context *ctx, mbedtls_pk_debug_item *items ) { - if( ctx == NULL || ctx->pk_info == NULL ) + PK_VALIDATE_RET( ctx != NULL ); + if( ctx->pk_info == NULL ) return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); if( ctx->pk_info->debug_func == NULL ) diff --git a/thirdparty/mbedtls/library/pk_wrap.c b/thirdparty/mbedtls/library/pk_wrap.c index 2c7d2d79b8..87806be337 100644 --- a/thirdparty/mbedtls/library/pk_wrap.c +++ b/thirdparty/mbedtls/library/pk_wrap.c @@ -190,11 +190,19 @@ const mbedtls_pk_info_t mbedtls_rsa_info = { rsa_can_do, rsa_verify_wrap, rsa_sign_wrap, +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + NULL, + NULL, +#endif rsa_decrypt_wrap, rsa_encrypt_wrap, rsa_check_pair_wrap, rsa_alloc_wrap, rsa_free_wrap, +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + NULL, + NULL, +#endif rsa_debug, }; #endif /* MBEDTLS_RSA_C */ @@ -262,6 +270,110 @@ static int eckey_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, return( ret ); } +#if defined(MBEDTLS_ECP_RESTARTABLE) +/* Forward declarations */ +static int ecdsa_verify_rs_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len, + void *rs_ctx ); + +static int ecdsa_sign_rs_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + void *rs_ctx ); + +/* + * Restart context for ECDSA operations with ECKEY context + * + * We need to store an actual ECDSA context, as we need to pass the same to + * the underlying ecdsa function, so we can't create it on the fly every time. + */ +typedef struct +{ + mbedtls_ecdsa_restart_ctx ecdsa_rs; + mbedtls_ecdsa_context ecdsa_ctx; +} eckey_restart_ctx; + +static void *eckey_rs_alloc( void ) +{ + eckey_restart_ctx *rs_ctx; + + void *ctx = mbedtls_calloc( 1, sizeof( eckey_restart_ctx ) ); + + if( ctx != NULL ) + { + rs_ctx = ctx; + mbedtls_ecdsa_restart_init( &rs_ctx->ecdsa_rs ); + mbedtls_ecdsa_init( &rs_ctx->ecdsa_ctx ); + } + + return( ctx ); +} + +static void eckey_rs_free( void *ctx ) +{ + eckey_restart_ctx *rs_ctx; + + if( ctx == NULL) + return; + + rs_ctx = ctx; + mbedtls_ecdsa_restart_free( &rs_ctx->ecdsa_rs ); + mbedtls_ecdsa_free( &rs_ctx->ecdsa_ctx ); + + mbedtls_free( ctx ); +} + +static int eckey_verify_rs_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len, + void *rs_ctx ) +{ + int ret; + eckey_restart_ctx *rs = rs_ctx; + + /* Should never happen */ + if( rs == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + /* set up our own sub-context if needed (that is, on first run) */ + if( rs->ecdsa_ctx.grp.pbits == 0 ) + MBEDTLS_MPI_CHK( mbedtls_ecdsa_from_keypair( &rs->ecdsa_ctx, ctx ) ); + + MBEDTLS_MPI_CHK( ecdsa_verify_rs_wrap( &rs->ecdsa_ctx, + md_alg, hash, hash_len, + sig, sig_len, &rs->ecdsa_rs ) ); + +cleanup: + return( ret ); +} + +static int eckey_sign_rs_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + void *rs_ctx ) +{ + int ret; + eckey_restart_ctx *rs = rs_ctx; + + /* Should never happen */ + if( rs == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + /* set up our own sub-context if needed (that is, on first run) */ + if( rs->ecdsa_ctx.grp.pbits == 0 ) + MBEDTLS_MPI_CHK( mbedtls_ecdsa_from_keypair( &rs->ecdsa_ctx, ctx ) ); + + MBEDTLS_MPI_CHK( ecdsa_sign_rs_wrap( &rs->ecdsa_ctx, md_alg, + hash, hash_len, sig, sig_len, + f_rng, p_rng, &rs->ecdsa_rs ) ); + +cleanup: + return( ret ); +} +#endif /* MBEDTLS_ECP_RESTARTABLE */ #endif /* MBEDTLS_ECDSA_C */ static int eckey_check_pair( const void *pub, const void *prv ) @@ -301,15 +413,23 @@ const mbedtls_pk_info_t mbedtls_eckey_info = { #if defined(MBEDTLS_ECDSA_C) eckey_verify_wrap, eckey_sign_wrap, -#else +#if defined(MBEDTLS_ECP_RESTARTABLE) + eckey_verify_rs_wrap, + eckey_sign_rs_wrap, +#endif +#else /* MBEDTLS_ECDSA_C */ NULL, NULL, -#endif +#endif /* MBEDTLS_ECDSA_C */ NULL, NULL, eckey_check_pair, eckey_alloc_wrap, eckey_free_wrap, +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + eckey_rs_alloc, + eckey_rs_free, +#endif eckey_debug, }; @@ -329,11 +449,19 @@ const mbedtls_pk_info_t mbedtls_eckeydh_info = { eckeydh_can_do, NULL, NULL, +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + NULL, + NULL, +#endif NULL, NULL, eckey_check_pair, eckey_alloc_wrap, /* Same underlying key structure */ eckey_free_wrap, /* Same underlying key structure */ +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + NULL, + NULL, +#endif eckey_debug, /* Same underlying key structure */ }; #endif /* MBEDTLS_ECP_C */ @@ -369,6 +497,40 @@ static int ecdsa_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, md_alg, hash, hash_len, sig, sig_len, f_rng, p_rng ) ); } +#if defined(MBEDTLS_ECP_RESTARTABLE) +static int ecdsa_verify_rs_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len, + void *rs_ctx ) +{ + int ret; + ((void) md_alg); + + ret = mbedtls_ecdsa_read_signature_restartable( + (mbedtls_ecdsa_context *) ctx, + hash, hash_len, sig, sig_len, + (mbedtls_ecdsa_restart_ctx *) rs_ctx ); + + if( ret == MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH ) + return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH ); + + return( ret ); +} + +static int ecdsa_sign_rs_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + void *rs_ctx ) +{ + return( mbedtls_ecdsa_write_signature_restartable( + (mbedtls_ecdsa_context *) ctx, + md_alg, hash, hash_len, sig, sig_len, f_rng, p_rng, + (mbedtls_ecdsa_restart_ctx *) rs_ctx ) ); + +} +#endif /* MBEDTLS_ECP_RESTARTABLE */ + static void *ecdsa_alloc_wrap( void ) { void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ecdsa_context ) ); @@ -385,6 +547,24 @@ static void ecdsa_free_wrap( void *ctx ) mbedtls_free( ctx ); } +#if defined(MBEDTLS_ECP_RESTARTABLE) +static void *ecdsa_rs_alloc( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ecdsa_restart_ctx ) ); + + if( ctx != NULL ) + mbedtls_ecdsa_restart_init( ctx ); + + return( ctx ); +} + +static void ecdsa_rs_free( void *ctx ) +{ + mbedtls_ecdsa_restart_free( ctx ); + mbedtls_free( ctx ); +} +#endif /* MBEDTLS_ECP_RESTARTABLE */ + const mbedtls_pk_info_t mbedtls_ecdsa_info = { MBEDTLS_PK_ECDSA, "ECDSA", @@ -392,11 +572,19 @@ const mbedtls_pk_info_t mbedtls_ecdsa_info = { ecdsa_can_do, ecdsa_verify_wrap, ecdsa_sign_wrap, +#if defined(MBEDTLS_ECP_RESTARTABLE) + ecdsa_verify_rs_wrap, + ecdsa_sign_rs_wrap, +#endif NULL, NULL, eckey_check_pair, /* Compatible key structures */ ecdsa_alloc_wrap, ecdsa_free_wrap, +#if defined(MBEDTLS_ECP_RESTARTABLE) + ecdsa_rs_alloc, + ecdsa_rs_free, +#endif eckey_debug, /* Compatible key structures */ }; #endif /* MBEDTLS_ECDSA_C */ @@ -506,6 +694,10 @@ const mbedtls_pk_info_t mbedtls_rsa_alt_info = { rsa_alt_can_do, NULL, rsa_alt_sign_wrap, +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + NULL, + NULL, +#endif rsa_alt_decrypt_wrap, NULL, #if defined(MBEDTLS_RSA_C) @@ -515,6 +707,10 @@ const mbedtls_pk_info_t mbedtls_rsa_alt_info = { #endif rsa_alt_alloc_wrap, rsa_alt_free_wrap, +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + NULL, + NULL, +#endif NULL, }; diff --git a/thirdparty/mbedtls/library/pkcs12.c b/thirdparty/mbedtls/library/pkcs12.c index 16a15cb63e..7edf064c13 100644 --- a/thirdparty/mbedtls/library/pkcs12.c +++ b/thirdparty/mbedtls/library/pkcs12.c @@ -48,6 +48,8 @@ #include "mbedtls/des.h" #endif +#if defined(MBEDTLS_ASN1_PARSE_C) + static int pkcs12_parse_pbe_params( mbedtls_asn1_buf *params, mbedtls_asn1_buf *salt, int *iterations ) { @@ -226,6 +228,8 @@ exit: return( ret ); } +#endif /* MBEDTLS_ASN1_PARSE_C */ + static void pkcs12_fill_buffer( unsigned char *data, size_t data_len, const unsigned char *filler, size_t fill_len ) { diff --git a/thirdparty/mbedtls/library/pkcs5.c b/thirdparty/mbedtls/library/pkcs5.c index f04f0ab25e..50133435ce 100644 --- a/thirdparty/mbedtls/library/pkcs5.c +++ b/thirdparty/mbedtls/library/pkcs5.c @@ -54,22 +54,7 @@ #define mbedtls_printf printf #endif -#if !defined(MBEDTLS_ASN1_PARSE_C) -int mbedtls_pkcs5_pbes2( const mbedtls_asn1_buf *pbe_params, int mode, - const unsigned char *pwd, size_t pwdlen, - const unsigned char *data, size_t datalen, - unsigned char *output ) -{ - ((void) pbe_params); - ((void) mode); - ((void) pwd); - ((void) pwdlen); - ((void) data); - ((void) datalen); - ((void) output); - return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); -} -#else +#if defined(MBEDTLS_ASN1_PARSE_C) static int pkcs5_parse_pbkdf2_params( const mbedtls_asn1_buf *params, mbedtls_asn1_buf *salt, int *iterations, int *keylen, mbedtls_md_type_t *md_type ) diff --git a/thirdparty/mbedtls/library/pkparse.c b/thirdparty/mbedtls/library/pkparse.c index d6ac987e23..ae210bca6a 100644 --- a/thirdparty/mbedtls/library/pkparse.c +++ b/thirdparty/mbedtls/library/pkparse.c @@ -61,6 +61,12 @@ #define mbedtls_free free #endif +/* Parameter validation macros based on platform_util.h */ +#define PK_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_PK_BAD_INPUT_DATA ) +#define PK_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + #if defined(MBEDTLS_FS_IO) /* * Load all data from a file into a given buffer. @@ -74,6 +80,10 @@ int mbedtls_pk_load_file( const char *path, unsigned char **buf, size_t *n ) FILE *f; long size; + PK_VALIDATE_RET( path != NULL ); + PK_VALIDATE_RET( buf != NULL ); + PK_VALIDATE_RET( n != NULL ); + if( ( f = fopen( path, "rb" ) ) == NULL ) return( MBEDTLS_ERR_PK_FILE_IO_ERROR ); @@ -124,6 +134,9 @@ int mbedtls_pk_parse_keyfile( mbedtls_pk_context *ctx, size_t n; unsigned char *buf; + PK_VALIDATE_RET( ctx != NULL ); + PK_VALIDATE_RET( path != NULL ); + if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 ) return( ret ); @@ -148,6 +161,9 @@ int mbedtls_pk_parse_public_keyfile( mbedtls_pk_context *ctx, const char *path ) size_t n; unsigned char *buf; + PK_VALIDATE_RET( ctx != NULL ); + PK_VALIDATE_RET( path != NULL ); + if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 ) return( ret ); @@ -605,6 +621,11 @@ int mbedtls_pk_parse_subpubkey( unsigned char **p, const unsigned char *end, mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; const mbedtls_pk_info_t *pk_info; + PK_VALIDATE_RET( p != NULL ); + PK_VALIDATE_RET( *p != NULL ); + PK_VALIDATE_RET( end != NULL ); + PK_VALIDATE_RET( pk != NULL ); + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) { @@ -1145,16 +1166,22 @@ int mbedtls_pk_parse_key( mbedtls_pk_context *pk, { int ret; const mbedtls_pk_info_t *pk_info; - #if defined(MBEDTLS_PEM_PARSE_C) size_t len; mbedtls_pem_context pem; +#endif - mbedtls_pem_init( &pem ); + PK_VALIDATE_RET( pk != NULL ); + if( keylen == 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); + PK_VALIDATE_RET( key != NULL ); + +#if defined(MBEDTLS_PEM_PARSE_C) + mbedtls_pem_init( &pem ); #if defined(MBEDTLS_RSA_C) /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ - if( keylen == 0 || key[keylen - 1] != '\0' ) + if( key[keylen - 1] != '\0' ) ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; else ret = mbedtls_pem_read_buffer( &pem, @@ -1185,7 +1212,7 @@ int mbedtls_pk_parse_key( mbedtls_pk_context *pk, #if defined(MBEDTLS_ECP_C) /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ - if( keylen == 0 || key[keylen - 1] != '\0' ) + if( key[keylen - 1] != '\0' ) ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; else ret = mbedtls_pem_read_buffer( &pem, @@ -1215,7 +1242,7 @@ int mbedtls_pk_parse_key( mbedtls_pk_context *pk, #endif /* MBEDTLS_ECP_C */ /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ - if( keylen == 0 || key[keylen - 1] != '\0' ) + if( key[keylen - 1] != '\0' ) ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; else ret = mbedtls_pem_read_buffer( &pem, @@ -1238,7 +1265,7 @@ int mbedtls_pk_parse_key( mbedtls_pk_context *pk, #if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ - if( keylen == 0 || key[keylen - 1] != '\0' ) + if( key[keylen - 1] != '\0' ) ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; else ret = mbedtls_pem_read_buffer( &pem, @@ -1276,9 +1303,6 @@ int mbedtls_pk_parse_key( mbedtls_pk_context *pk, { unsigned char *key_copy; - if( keylen == 0 ) - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); - if( ( key_copy = mbedtls_calloc( 1, keylen ) ) == NULL ) return( MBEDTLS_ERR_PK_ALLOC_FAILED ); @@ -1295,6 +1319,7 @@ int mbedtls_pk_parse_key( mbedtls_pk_context *pk, return( 0 ); mbedtls_pk_free( pk ); + mbedtls_pk_init( pk ); if( ret == MBEDTLS_ERR_PK_PASSWORD_MISMATCH ) { @@ -1306,39 +1331,42 @@ int mbedtls_pk_parse_key( mbedtls_pk_context *pk, return( 0 ); mbedtls_pk_free( pk ); + mbedtls_pk_init( pk ); #if defined(MBEDTLS_RSA_C) pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ); - if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 || - ( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), - key, keylen ) ) != 0 ) - { - mbedtls_pk_free( pk ); - } - else + if( mbedtls_pk_setup( pk, pk_info ) == 0 && + pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), key, keylen ) == 0 ) { return( 0 ); } + mbedtls_pk_free( pk ); + mbedtls_pk_init( pk ); #endif /* MBEDTLS_RSA_C */ #if defined(MBEDTLS_ECP_C) - pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY ); - if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 || - ( ret = pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ), - key, keylen ) ) != 0 ) - { - mbedtls_pk_free( pk ); - } - else + if( mbedtls_pk_setup( pk, pk_info ) == 0 && + pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ), + key, keylen ) == 0 ) { return( 0 ); } - + mbedtls_pk_free( pk ); #endif /* MBEDTLS_ECP_C */ + /* If MBEDTLS_RSA_C is defined but MBEDTLS_ECP_C isn't, + * it is ok to leave the PK context initialized but not + * freed: It is the caller's responsibility to call pk_init() + * before calling this function, and to call pk_free() + * when it fails. If MBEDTLS_ECP_C is defined but MBEDTLS_RSA_C + * isn't, this leads to mbedtls_pk_free() being called + * twice, once here and once by the caller, but this is + * also ok and in line with the mbedtls_pk_free() calls + * on failed PEM parsing attempts. */ + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); } @@ -1356,11 +1384,18 @@ int mbedtls_pk_parse_public_key( mbedtls_pk_context *ctx, #if defined(MBEDTLS_PEM_PARSE_C) size_t len; mbedtls_pem_context pem; +#endif + PK_VALIDATE_RET( ctx != NULL ); + if( keylen == 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); + PK_VALIDATE_RET( key != NULL || keylen == 0 ); + +#if defined(MBEDTLS_PEM_PARSE_C) mbedtls_pem_init( &pem ); #if defined(MBEDTLS_RSA_C) /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ - if( keylen == 0 || key[keylen - 1] != '\0' ) + if( key[keylen - 1] != '\0' ) ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; else ret = mbedtls_pem_read_buffer( &pem, @@ -1391,7 +1426,7 @@ int mbedtls_pk_parse_public_key( mbedtls_pk_context *ctx, #endif /* MBEDTLS_RSA_C */ /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ - if( keylen == 0 || key[keylen - 1] != '\0' ) + if( key[keylen - 1] != '\0' ) ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; else ret = mbedtls_pem_read_buffer( &pem, diff --git a/thirdparty/mbedtls/library/pkwrite.c b/thirdparty/mbedtls/library/pkwrite.c index 8eabd889b5..8d1da2f757 100644 --- a/thirdparty/mbedtls/library/pkwrite.c +++ b/thirdparty/mbedtls/library/pkwrite.c @@ -30,6 +30,7 @@ #include "mbedtls/pk.h" #include "mbedtls/asn1write.h" #include "mbedtls/oid.h" +#include "mbedtls/platform_util.h" #include <string.h> @@ -54,6 +55,12 @@ #define mbedtls_free free #endif +/* Parameter validation macros based on platform_util.h */ +#define PK_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_PK_BAD_INPUT_DATA ) +#define PK_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + #if defined(MBEDTLS_RSA_C) /* * RSAPublicKey ::= SEQUENCE { @@ -151,6 +158,11 @@ int mbedtls_pk_write_pubkey( unsigned char **p, unsigned char *start, int ret; size_t len = 0; + PK_VALIDATE_RET( p != NULL ); + PK_VALIDATE_RET( *p != NULL ); + PK_VALIDATE_RET( start != NULL ); + PK_VALIDATE_RET( key != NULL ); + #if defined(MBEDTLS_RSA_C) if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_RSA ) MBEDTLS_ASN1_CHK_ADD( len, pk_write_rsa_pubkey( p, start, mbedtls_pk_rsa( *key ) ) ); @@ -173,6 +185,11 @@ int mbedtls_pk_write_pubkey_der( mbedtls_pk_context *key, unsigned char *buf, si size_t len = 0, par_len = 0, oid_len; const char *oid; + PK_VALIDATE_RET( key != NULL ); + if( size == 0 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + PK_VALIDATE_RET( buf != NULL ); + c = buf + size; MBEDTLS_ASN1_CHK_ADD( len, mbedtls_pk_write_pubkey( &c, buf, key ) ); @@ -217,9 +234,16 @@ int mbedtls_pk_write_pubkey_der( mbedtls_pk_context *key, unsigned char *buf, si int mbedtls_pk_write_key_der( mbedtls_pk_context *key, unsigned char *buf, size_t size ) { int ret; - unsigned char *c = buf + size; + unsigned char *c; size_t len = 0; + PK_VALIDATE_RET( key != NULL ); + if( size == 0 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + PK_VALIDATE_RET( buf != NULL ); + + c = buf + size; + #if defined(MBEDTLS_RSA_C) if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_RSA ) { @@ -457,6 +481,9 @@ int mbedtls_pk_write_pubkey_pem( mbedtls_pk_context *key, unsigned char *buf, si unsigned char output_buf[PUB_DER_MAX_BYTES]; size_t olen = 0; + PK_VALIDATE_RET( key != NULL ); + PK_VALIDATE_RET( buf != NULL || size == 0 ); + if( ( ret = mbedtls_pk_write_pubkey_der( key, output_buf, sizeof(output_buf) ) ) < 0 ) { @@ -480,6 +507,9 @@ int mbedtls_pk_write_key_pem( mbedtls_pk_context *key, unsigned char *buf, size_ const char *begin, *end; size_t olen = 0; + PK_VALIDATE_RET( key != NULL ); + PK_VALIDATE_RET( buf != NULL || size == 0 ); + if( ( ret = mbedtls_pk_write_key_der( key, output_buf, sizeof(output_buf) ) ) < 0 ) return( ret ); diff --git a/thirdparty/mbedtls/library/platform.c b/thirdparty/mbedtls/library/platform.c index b24b2fa652..73a6db9ebe 100644 --- a/thirdparty/mbedtls/library/platform.c +++ b/thirdparty/mbedtls/library/platform.c @@ -30,7 +30,14 @@ #include "mbedtls/platform.h" #include "mbedtls/platform_util.h" -#if defined(MBEDTLS_PLATFORM_MEMORY) +/* The compile time configuration of memory allocation via the macros + * MBEDTLS_PLATFORM_{FREE/CALLOC}_MACRO takes precedence over the runtime + * configuration via mbedtls_platform_set_calloc_free(). So, omit everything + * related to the latter if MBEDTLS_PLATFORM_{FREE/CALLOC}_MACRO are defined. */ +#if defined(MBEDTLS_PLATFORM_MEMORY) && \ + !( defined(MBEDTLS_PLATFORM_CALLOC_MACRO) && \ + defined(MBEDTLS_PLATFORM_FREE_MACRO) ) + #if !defined(MBEDTLS_PLATFORM_STD_CALLOC) static void *platform_calloc_uninit( size_t n, size_t size ) { @@ -71,7 +78,9 @@ int mbedtls_platform_set_calloc_free( void * (*calloc_func)( size_t, size_t ), mbedtls_free_func = free_func; return( 0 ); } -#endif /* MBEDTLS_PLATFORM_MEMORY */ +#endif /* MBEDTLS_PLATFORM_MEMORY && + !( defined(MBEDTLS_PLATFORM_CALLOC_MACRO) && + defined(MBEDTLS_PLATFORM_FREE_MACRO) ) */ #if defined(_WIN32) #include <stdarg.h> diff --git a/thirdparty/mbedtls/library/platform_util.c b/thirdparty/mbedtls/library/platform_util.c index 1a57de9393..756e22679a 100644 --- a/thirdparty/mbedtls/library/platform_util.c +++ b/thirdparty/mbedtls/library/platform_util.c @@ -20,6 +20,14 @@ * This file is part of Mbed TLS (https://tls.mbed.org) */ +/* + * Ensure gmtime_r is available even with -std=c99; must be defined before + * config.h, which pulls in glibc's features.h. Harmless on other platforms. + */ +#if !defined(_POSIX_C_SOURCE) +#define _POSIX_C_SOURCE 200112L +#endif + #if !defined(MBEDTLS_CONFIG_FILE) #include "mbedtls/config.h" #else @@ -27,6 +35,8 @@ #endif #include "mbedtls/platform_util.h" +#include "mbedtls/platform.h" +#include "mbedtls/threading.h" #include <stddef.h> #include <string.h> @@ -65,3 +75,62 @@ void mbedtls_platform_zeroize( void *buf, size_t len ) memset_func( buf, 0, len ); } #endif /* MBEDTLS_PLATFORM_ZEROIZE_ALT */ + +#if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_PLATFORM_GMTIME_R_ALT) +#include <time.h> +#if !defined(_WIN32) && (defined(unix) || \ + defined(__unix) || defined(__unix__) || (defined(__APPLE__) && \ + defined(__MACH__))) +#include <unistd.h> +#endif /* !_WIN32 && (unix || __unix || __unix__ || + * (__APPLE__ && __MACH__)) */ + +#if !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) || \ + ( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) && \ + _POSIX_THREAD_SAFE_FUNCTIONS >= 20112L ) ) +/* + * This is a convenience shorthand macro to avoid checking the long + * preprocessor conditions above. Ideally, we could expose this macro in + * platform_util.h and simply use it in platform_util.c, threading.c and + * threading.h. However, this macro is not part of the Mbed TLS public API, so + * we keep it private by only defining it in this file + */ +#if ! ( defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) ) +#define PLATFORM_UTIL_USE_GMTIME +#endif /* ! ( defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) ) */ + +#endif /* !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) || \ + ( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) && \ + _POSIX_THREAD_SAFE_FUNCTIONS >= 20112L ) ) */ + +struct tm *mbedtls_platform_gmtime_r( const mbedtls_time_t *tt, + struct tm *tm_buf ) +{ +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) + return( ( gmtime_s( tm_buf, tt ) == 0 ) ? tm_buf : NULL ); +#elif !defined(PLATFORM_UTIL_USE_GMTIME) + return( gmtime_r( tt, tm_buf ) ); +#else + struct tm *lt; + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_lock( &mbedtls_threading_gmtime_mutex ) != 0 ) + return( NULL ); +#endif /* MBEDTLS_THREADING_C */ + + lt = gmtime( tt ); + + if( lt != NULL ) + { + memcpy( tm_buf, lt, sizeof( struct tm ) ); + } + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &mbedtls_threading_gmtime_mutex ) != 0 ) + return( NULL ); +#endif /* MBEDTLS_THREADING_C */ + + return( ( lt == NULL ) ? NULL : tm_buf ); +#endif /* _WIN32 && !EFIX64 && !EFI32 */ +} +#endif /* MBEDTLS_HAVE_TIME_DATE && MBEDTLS_PLATFORM_GMTIME_R_ALT */ diff --git a/thirdparty/mbedtls/library/poly1305.c b/thirdparty/mbedtls/library/poly1305.c index e22d3afb68..b274119181 100644 --- a/thirdparty/mbedtls/library/poly1305.c +++ b/thirdparty/mbedtls/library/poly1305.c @@ -49,6 +49,12 @@ #define inline __inline #endif +/* Parameter validation macros */ +#define POLY1305_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA ) +#define POLY1305_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + #define POLY1305_BLOCK_SIZE_BYTES ( 16U ) #define BYTES_TO_U32_LE( data, offset ) \ @@ -276,27 +282,24 @@ static void poly1305_compute_mac( const mbedtls_poly1305_context *ctx, void mbedtls_poly1305_init( mbedtls_poly1305_context *ctx ) { - if( ctx != NULL ) - { - mbedtls_platform_zeroize( ctx, sizeof( mbedtls_poly1305_context ) ); - } + POLY1305_VALIDATE( ctx != NULL ); + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_poly1305_context ) ); } void mbedtls_poly1305_free( mbedtls_poly1305_context *ctx ) { - if( ctx != NULL ) - { - mbedtls_platform_zeroize( ctx, sizeof( mbedtls_poly1305_context ) ); - } + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_poly1305_context ) ); } int mbedtls_poly1305_starts( mbedtls_poly1305_context *ctx, const unsigned char key[32] ) { - if( ctx == NULL || key == NULL ) - { - return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA ); - } + POLY1305_VALIDATE_RET( ctx != NULL ); + POLY1305_VALIDATE_RET( key != NULL ); /* r &= 0x0ffffffc0ffffffc0ffffffc0fffffff */ ctx->r[0] = BYTES_TO_U32_LE( key, 0 ) & 0x0FFFFFFFU; @@ -331,16 +334,8 @@ int mbedtls_poly1305_update( mbedtls_poly1305_context *ctx, size_t remaining = ilen; size_t queue_free_len; size_t nblocks; - - if( ctx == NULL ) - { - return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA ); - } - else if( ( ilen > 0U ) && ( input == NULL ) ) - { - /* input pointer is allowed to be NULL only if ilen == 0 */ - return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA ); - } + POLY1305_VALIDATE_RET( ctx != NULL ); + POLY1305_VALIDATE_RET( ilen == 0 || input != NULL ); if( ( remaining > 0U ) && ( ctx->queue_len > 0U ) ) { @@ -398,10 +393,8 @@ int mbedtls_poly1305_update( mbedtls_poly1305_context *ctx, int mbedtls_poly1305_finish( mbedtls_poly1305_context *ctx, unsigned char mac[16] ) { - if( ( ctx == NULL ) || ( mac == NULL ) ) - { - return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA ); - } + POLY1305_VALIDATE_RET( ctx != NULL ); + POLY1305_VALIDATE_RET( mac != NULL ); /* Process any leftover data */ if( ctx->queue_len > 0U ) @@ -431,6 +424,9 @@ int mbedtls_poly1305_mac( const unsigned char key[32], { mbedtls_poly1305_context ctx; int ret; + POLY1305_VALIDATE_RET( key != NULL ); + POLY1305_VALIDATE_RET( mac != NULL ); + POLY1305_VALIDATE_RET( ilen == 0 || input != NULL ); mbedtls_poly1305_init( &ctx ); diff --git a/thirdparty/mbedtls/library/rsa.c b/thirdparty/mbedtls/library/rsa.c index 88c1cf1007..af1a878599 100644 --- a/thirdparty/mbedtls/library/rsa.c +++ b/thirdparty/mbedtls/library/rsa.c @@ -71,6 +71,12 @@ #if !defined(MBEDTLS_RSA_ALT) +/* Parameter validation macros */ +#define RSA_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_RSA_BAD_INPUT_DATA ) +#define RSA_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + #if defined(MBEDTLS_PKCS1_V15) /* constant-time buffer comparison */ static inline int mbedtls_safer_memcmp( const void *a, const void *b, size_t n ) @@ -93,6 +99,7 @@ int mbedtls_rsa_import( mbedtls_rsa_context *ctx, const mbedtls_mpi *D, const mbedtls_mpi *E ) { int ret; + RSA_VALIDATE_RET( ctx != NULL ); if( ( N != NULL && ( ret = mbedtls_mpi_copy( &ctx->N, N ) ) != 0 ) || ( P != NULL && ( ret = mbedtls_mpi_copy( &ctx->P, P ) ) != 0 ) || @@ -117,6 +124,7 @@ int mbedtls_rsa_import_raw( mbedtls_rsa_context *ctx, unsigned char const *E, size_t E_len ) { int ret = 0; + RSA_VALIDATE_RET( ctx != NULL ); if( N != NULL ) { @@ -240,12 +248,16 @@ static int rsa_check_context( mbedtls_rsa_context const *ctx, int is_priv, int mbedtls_rsa_complete( mbedtls_rsa_context *ctx ) { int ret = 0; + int have_N, have_P, have_Q, have_D, have_E; + int n_missing, pq_missing, d_missing, is_pub, is_priv; + + RSA_VALIDATE_RET( ctx != NULL ); - const int have_N = ( mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 ); - const int have_P = ( mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 ); - const int have_Q = ( mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 ); - const int have_D = ( mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 ); - const int have_E = ( mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0 ); + have_N = ( mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 ); + have_P = ( mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 ); + have_Q = ( mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 ); + have_D = ( mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 ); + have_E = ( mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0 ); /* * Check whether provided parameters are enough @@ -257,13 +269,13 @@ int mbedtls_rsa_complete( mbedtls_rsa_context *ctx ) * */ - const int n_missing = have_P && have_Q && have_D && have_E; - const int pq_missing = have_N && !have_P && !have_Q && have_D && have_E; - const int d_missing = have_P && have_Q && !have_D && have_E; - const int is_pub = have_N && !have_P && !have_Q && !have_D && have_E; + n_missing = have_P && have_Q && have_D && have_E; + pq_missing = have_N && !have_P && !have_Q && have_D && have_E; + d_missing = have_P && have_Q && !have_D && have_E; + is_pub = have_N && !have_P && !have_Q && !have_D && have_E; /* These three alternatives are mutually exclusive */ - const int is_priv = n_missing || pq_missing || d_missing; + is_priv = n_missing || pq_missing || d_missing; if( !is_priv && !is_pub ) return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); @@ -336,9 +348,11 @@ int mbedtls_rsa_export_raw( const mbedtls_rsa_context *ctx, unsigned char *E, size_t E_len ) { int ret = 0; + int is_priv; + RSA_VALIDATE_RET( ctx != NULL ); /* Check if key is private or public */ - const int is_priv = + is_priv = mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 && mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 && mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 && @@ -379,9 +393,11 @@ int mbedtls_rsa_export( const mbedtls_rsa_context *ctx, mbedtls_mpi *D, mbedtls_mpi *E ) { int ret; + int is_priv; + RSA_VALIDATE_RET( ctx != NULL ); /* Check if key is private or public */ - int is_priv = + is_priv = mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 && mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 && mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 && @@ -421,9 +437,11 @@ int mbedtls_rsa_export_crt( const mbedtls_rsa_context *ctx, mbedtls_mpi *DP, mbedtls_mpi *DQ, mbedtls_mpi *QP ) { int ret; + int is_priv; + RSA_VALIDATE_RET( ctx != NULL ); /* Check if key is private or public */ - int is_priv = + is_priv = mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 && mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 && mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 && @@ -459,6 +477,10 @@ void mbedtls_rsa_init( mbedtls_rsa_context *ctx, int padding, int hash_id ) { + RSA_VALIDATE( ctx != NULL ); + RSA_VALIDATE( padding == MBEDTLS_RSA_PKCS_V15 || + padding == MBEDTLS_RSA_PKCS_V21 ); + memset( ctx, 0, sizeof( mbedtls_rsa_context ) ); mbedtls_rsa_set_padding( ctx, padding, hash_id ); @@ -471,8 +493,13 @@ void mbedtls_rsa_init( mbedtls_rsa_context *ctx, /* * Set padding for an existing RSA context */ -void mbedtls_rsa_set_padding( mbedtls_rsa_context *ctx, int padding, int hash_id ) +void mbedtls_rsa_set_padding( mbedtls_rsa_context *ctx, int padding, + int hash_id ) { + RSA_VALIDATE( ctx != NULL ); + RSA_VALIDATE( padding == MBEDTLS_RSA_PKCS_V15 || + padding == MBEDTLS_RSA_PKCS_V21 ); + ctx->padding = padding; ctx->hash_id = hash_id; } @@ -502,12 +529,20 @@ int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx, { int ret; mbedtls_mpi H, G, L; + int prime_quality = 0; + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( f_rng != NULL ); - if( f_rng == NULL || nbits < 128 || exponent < 3 ) + if( nbits < 128 || exponent < 3 || nbits % 2 != 0 ) return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - if( nbits % 2 ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + /* + * If the modulus is 1024 bit long or shorter, then the security strength of + * the RSA algorithm is less than or equal to 80 bits and therefore an error + * rate of 2^-80 is sufficient. + */ + if( nbits > 1024 ) + prime_quality = MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR; mbedtls_mpi_init( &H ); mbedtls_mpi_init( &G ); @@ -523,11 +558,11 @@ int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx, do { - MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->P, nbits >> 1, 0, - f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->P, nbits >> 1, + prime_quality, f_rng, p_rng ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->Q, nbits >> 1, 0, - f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->Q, nbits >> 1, + prime_quality, f_rng, p_rng ) ); /* make sure the difference between p and q is not too small (FIPS 186-4 §B.3.3 step 5.4) */ MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &H, &ctx->P, &ctx->Q ) ); @@ -603,6 +638,8 @@ cleanup: */ int mbedtls_rsa_check_pubkey( const mbedtls_rsa_context *ctx ) { + RSA_VALIDATE_RET( ctx != NULL ); + if( rsa_check_context( ctx, 0 /* public */, 0 /* no blinding */ ) != 0 ) return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); @@ -626,6 +663,8 @@ int mbedtls_rsa_check_pubkey( const mbedtls_rsa_context *ctx ) */ int mbedtls_rsa_check_privkey( const mbedtls_rsa_context *ctx ) { + RSA_VALIDATE_RET( ctx != NULL ); + if( mbedtls_rsa_check_pubkey( ctx ) != 0 || rsa_check_context( ctx, 1 /* private */, 1 /* blinding */ ) != 0 ) { @@ -655,6 +694,9 @@ int mbedtls_rsa_check_privkey( const mbedtls_rsa_context *ctx ) int mbedtls_rsa_check_pub_priv( const mbedtls_rsa_context *pub, const mbedtls_rsa_context *prv ) { + RSA_VALIDATE_RET( pub != NULL ); + RSA_VALIDATE_RET( prv != NULL ); + if( mbedtls_rsa_check_pubkey( pub ) != 0 || mbedtls_rsa_check_privkey( prv ) != 0 ) { @@ -680,6 +722,9 @@ int mbedtls_rsa_public( mbedtls_rsa_context *ctx, int ret; size_t olen; mbedtls_mpi T; + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( input != NULL ); + RSA_VALIDATE_RET( output != NULL ); if( rsa_check_context( ctx, 0 /* public */, 0 /* no blinding */ ) ) return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); @@ -822,6 +867,10 @@ int mbedtls_rsa_private( mbedtls_rsa_context *ctx, * checked result; should be the same in the end. */ mbedtls_mpi I, C; + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( input != NULL ); + RSA_VALIDATE_RET( output != NULL ); + if( rsa_check_context( ctx, 1 /* private key checks */, f_rng != NULL /* blinding y/n */ ) != 0 ) { @@ -1082,6 +1131,13 @@ int mbedtls_rsa_rsaes_oaep_encrypt( mbedtls_rsa_context *ctx, const mbedtls_md_info_t *md_info; mbedtls_md_context_t md_ctx; + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( output != NULL ); + RSA_VALIDATE_RET( input != NULL ); + RSA_VALIDATE_RET( label_len == 0 || label != NULL ); + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 ) return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); @@ -1158,11 +1214,13 @@ int mbedtls_rsa_rsaes_pkcs1_v15_encrypt( mbedtls_rsa_context *ctx, int ret; unsigned char *p = output; - if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( output != NULL ); + RSA_VALIDATE_RET( input != NULL ); - // We don't check p_rng because it won't be dereferenced here - if( f_rng == NULL || input == NULL || output == NULL ) + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); olen = ctx->len; @@ -1176,6 +1234,9 @@ int mbedtls_rsa_rsaes_pkcs1_v15_encrypt( mbedtls_rsa_context *ctx, *p++ = 0; if( mode == MBEDTLS_RSA_PUBLIC ) { + if( f_rng == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + *p++ = MBEDTLS_RSA_CRYPT; while( nb_pad-- > 0 ) @@ -1220,6 +1281,12 @@ int mbedtls_rsa_pkcs1_encrypt( mbedtls_rsa_context *ctx, const unsigned char *input, unsigned char *output ) { + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( output != NULL ); + RSA_VALIDATE_RET( input != NULL ); + switch( ctx->padding ) { #if defined(MBEDTLS_PKCS1_V15) @@ -1262,6 +1329,14 @@ int mbedtls_rsa_rsaes_oaep_decrypt( mbedtls_rsa_context *ctx, const mbedtls_md_info_t *md_info; mbedtls_md_context_t md_ctx; + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( output_max_len == 0 || output != NULL ); + RSA_VALIDATE_RET( label_len == 0 || label != NULL ); + RSA_VALIDATE_RET( input != NULL ); + RSA_VALIDATE_RET( olen != NULL ); + /* * Parameters sanity checks */ @@ -1378,6 +1453,97 @@ cleanup: #endif /* MBEDTLS_PKCS1_V21 */ #if defined(MBEDTLS_PKCS1_V15) +/** Turn zero-or-nonzero into zero-or-all-bits-one, without branches. + * + * \param value The value to analyze. + * \return Zero if \p value is zero, otherwise all-bits-one. + */ +static unsigned all_or_nothing_int( unsigned value ) +{ + /* MSVC has a warning about unary minus on unsigned, but this is + * well-defined and precisely what we want to do here */ +#if defined(_MSC_VER) +#pragma warning( push ) +#pragma warning( disable : 4146 ) +#endif + return( - ( ( value | - value ) >> ( sizeof( value ) * 8 - 1 ) ) ); +#if defined(_MSC_VER) +#pragma warning( pop ) +#endif +} + +/** Check whether a size is out of bounds, without branches. + * + * This is equivalent to `size > max`, but is likely to be compiled to + * to code using bitwise operation rather than a branch. + * + * \param size Size to check. + * \param max Maximum desired value for \p size. + * \return \c 0 if `size <= max`. + * \return \c 1 if `size > max`. + */ +static unsigned size_greater_than( size_t size, size_t max ) +{ + /* Return the sign bit (1 for negative) of (max - size). */ + return( ( max - size ) >> ( sizeof( size_t ) * 8 - 1 ) ); +} + +/** Choose between two integer values, without branches. + * + * This is equivalent to `cond ? if1 : if0`, but is likely to be compiled + * to code using bitwise operation rather than a branch. + * + * \param cond Condition to test. + * \param if1 Value to use if \p cond is nonzero. + * \param if0 Value to use if \p cond is zero. + * \return \c if1 if \p cond is nonzero, otherwise \c if0. + */ +static unsigned if_int( unsigned cond, unsigned if1, unsigned if0 ) +{ + unsigned mask = all_or_nothing_int( cond ); + return( ( mask & if1 ) | (~mask & if0 ) ); +} + +/** Shift some data towards the left inside a buffer without leaking + * the length of the data through side channels. + * + * `mem_move_to_left(start, total, offset)` is functionally equivalent to + * ``` + * memmove(start, start + offset, total - offset); + * memset(start + offset, 0, total - offset); + * ``` + * but it strives to use a memory access pattern (and thus total timing) + * that does not depend on \p offset. This timing independence comes at + * the expense of performance. + * + * \param start Pointer to the start of the buffer. + * \param total Total size of the buffer. + * \param offset Offset from which to copy \p total - \p offset bytes. + */ +static void mem_move_to_left( void *start, + size_t total, + size_t offset ) +{ + volatile unsigned char *buf = start; + size_t i, n; + if( total == 0 ) + return; + for( i = 0; i < total; i++ ) + { + unsigned no_op = size_greater_than( total - offset, i ); + /* The first `total - offset` passes are a no-op. The last + * `offset` passes shift the data one byte to the left and + * zero out the last byte. */ + for( n = 0; n < total - 1; n++ ) + { + unsigned char current = buf[n]; + unsigned char next = buf[n+1]; + buf[n] = if_int( no_op, current, next ); + } + buf[total-1] = if_int( no_op, buf[total-1], 0 ); + } +} + /* * Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-DECRYPT function */ @@ -1387,18 +1553,42 @@ int mbedtls_rsa_rsaes_pkcs1_v15_decrypt( mbedtls_rsa_context *ctx, int mode, size_t *olen, const unsigned char *input, unsigned char *output, - size_t output_max_len) + size_t output_max_len ) { int ret; - size_t ilen, pad_count = 0, i; - unsigned char *p, bad, pad_done = 0; + size_t ilen, i, plaintext_max_size; unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; + /* The following variables take sensitive values: their value must + * not leak into the observable behavior of the function other than + * the designated outputs (output, olen, return value). Otherwise + * this would open the execution of the function to + * side-channel-based variants of the Bleichenbacher padding oracle + * attack. Potential side channels include overall timing, memory + * access patterns (especially visible to an adversary who has access + * to a shared memory cache), and branches (especially visible to + * an adversary who has access to a shared code cache or to a shared + * branch predictor). */ + size_t pad_count = 0; + unsigned bad = 0; + unsigned char pad_done = 0; + size_t plaintext_size = 0; + unsigned output_too_large; + + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( output_max_len == 0 || output != NULL ); + RSA_VALIDATE_RET( input != NULL ); + RSA_VALIDATE_RET( olen != NULL ); + + ilen = ctx->len; + plaintext_max_size = ( output_max_len > ilen - 11 ? + ilen - 11 : + output_max_len ); if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - ilen = ctx->len; - if( ilen < 16 || ilen > sizeof( buf ) ) return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); @@ -1409,63 +1599,109 @@ int mbedtls_rsa_rsaes_pkcs1_v15_decrypt( mbedtls_rsa_context *ctx, if( ret != 0 ) goto cleanup; - p = buf; - bad = 0; - - /* - * Check and get padding len in "constant-time" - */ - bad |= *p++; /* First byte must be 0 */ + /* Check and get padding length in constant time and constant + * memory trace. The first byte must be 0. */ + bad |= buf[0]; - /* This test does not depend on secret data */ if( mode == MBEDTLS_RSA_PRIVATE ) { - bad |= *p++ ^ MBEDTLS_RSA_CRYPT; + /* Decode EME-PKCS1-v1_5 padding: 0x00 || 0x02 || PS || 0x00 + * where PS must be at least 8 nonzero bytes. */ + bad |= buf[1] ^ MBEDTLS_RSA_CRYPT; - /* Get padding len, but always read till end of buffer - * (minus one, for the 00 byte) */ - for( i = 0; i < ilen - 3; i++ ) + /* Read the whole buffer. Set pad_done to nonzero if we find + * the 0x00 byte and remember the padding length in pad_count. */ + for( i = 2; i < ilen; i++ ) { - pad_done |= ((p[i] | (unsigned char)-p[i]) >> 7) ^ 1; + pad_done |= ((buf[i] | (unsigned char)-buf[i]) >> 7) ^ 1; pad_count += ((pad_done | (unsigned char)-pad_done) >> 7) ^ 1; } - - p += pad_count; - bad |= *p++; /* Must be zero */ } else { - bad |= *p++ ^ MBEDTLS_RSA_SIGN; + /* Decode EMSA-PKCS1-v1_5 padding: 0x00 || 0x01 || PS || 0x00 + * where PS must be at least 8 bytes with the value 0xFF. */ + bad |= buf[1] ^ MBEDTLS_RSA_SIGN; - /* Get padding len, but always read till end of buffer - * (minus one, for the 00 byte) */ - for( i = 0; i < ilen - 3; i++ ) + /* Read the whole buffer. Set pad_done to nonzero if we find + * the 0x00 byte and remember the padding length in pad_count. + * If there's a non-0xff byte in the padding, the padding is bad. */ + for( i = 2; i < ilen; i++ ) { - pad_done |= ( p[i] != 0xFF ); - pad_count += ( pad_done == 0 ); + pad_done |= if_int( buf[i], 0, 1 ); + pad_count += if_int( pad_done, 0, 1 ); + bad |= if_int( pad_done, 0, buf[i] ^ 0xFF ); } - - p += pad_count; - bad |= *p++; /* Must be zero */ } - bad |= ( pad_count < 8 ); - - if( bad ) - { - ret = MBEDTLS_ERR_RSA_INVALID_PADDING; - goto cleanup; - } - - if( ilen - ( p - buf ) > output_max_len ) - { - ret = MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE; - goto cleanup; - } - - *olen = ilen - (p - buf); - memcpy( output, p, *olen ); - ret = 0; + /* If pad_done is still zero, there's no data, only unfinished padding. */ + bad |= if_int( pad_done, 0, 1 ); + + /* There must be at least 8 bytes of padding. */ + bad |= size_greater_than( 8, pad_count ); + + /* If the padding is valid, set plaintext_size to the number of + * remaining bytes after stripping the padding. If the padding + * is invalid, avoid leaking this fact through the size of the + * output: use the maximum message size that fits in the output + * buffer. Do it without branches to avoid leaking the padding + * validity through timing. RSA keys are small enough that all the + * size_t values involved fit in unsigned int. */ + plaintext_size = if_int( bad, + (unsigned) plaintext_max_size, + (unsigned) ( ilen - pad_count - 3 ) ); + + /* Set output_too_large to 0 if the plaintext fits in the output + * buffer and to 1 otherwise. */ + output_too_large = size_greater_than( plaintext_size, + plaintext_max_size ); + + /* Set ret without branches to avoid timing attacks. Return: + * - INVALID_PADDING if the padding is bad (bad != 0). + * - OUTPUT_TOO_LARGE if the padding is good but the decrypted + * plaintext does not fit in the output buffer. + * - 0 if the padding is correct. */ + ret = - (int) if_int( bad, - MBEDTLS_ERR_RSA_INVALID_PADDING, + if_int( output_too_large, - MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE, + 0 ) ); + + /* If the padding is bad or the plaintext is too large, zero the + * data that we're about to copy to the output buffer. + * We need to copy the same amount of data + * from the same buffer whether the padding is good or not to + * avoid leaking the padding validity through overall timing or + * through memory or cache access patterns. */ + bad = all_or_nothing_int( bad | output_too_large ); + for( i = 11; i < ilen; i++ ) + buf[i] &= ~bad; + + /* If the plaintext is too large, truncate it to the buffer size. + * Copy anyway to avoid revealing the length through timing, because + * revealing the length is as bad as revealing the padding validity + * for a Bleichenbacher attack. */ + plaintext_size = if_int( output_too_large, + (unsigned) plaintext_max_size, + (unsigned) plaintext_size ); + + /* Move the plaintext to the leftmost position where it can start in + * the working buffer, i.e. make it start plaintext_max_size from + * the end of the buffer. Do this with a memory access trace that + * does not depend on the plaintext size. After this move, the + * starting location of the plaintext is no longer sensitive + * information. */ + mem_move_to_left( buf + ilen - plaintext_max_size, + plaintext_max_size, + plaintext_max_size - plaintext_size ); + + /* Finally copy the decrypted plaintext plus trailing zeros + * into the output buffer. */ + memcpy( output, buf + ilen - plaintext_max_size, plaintext_max_size ); + + /* Report the amount of data we copied to the output buffer. In case + * of errors (bad padding or output too large), the value of *olen + * when this function returns is not specified. Making it equivalent + * to the good case limits the risks of leaking the padding validity. */ + *olen = plaintext_size; cleanup: mbedtls_platform_zeroize( buf, sizeof( buf ) ); @@ -1485,6 +1721,13 @@ int mbedtls_rsa_pkcs1_decrypt( mbedtls_rsa_context *ctx, unsigned char *output, size_t output_max_len) { + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( output_max_len == 0 || output != NULL ); + RSA_VALIDATE_RET( input != NULL ); + RSA_VALIDATE_RET( olen != NULL ); + switch( ctx->padding ) { #if defined(MBEDTLS_PKCS1_V15) @@ -1521,11 +1764,18 @@ int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx, size_t olen; unsigned char *p = sig; unsigned char salt[MBEDTLS_MD_MAX_SIZE]; - unsigned int slen, hlen, offset = 0; + size_t slen, min_slen, hlen, offset = 0; int ret; size_t msb; const mbedtls_md_info_t *md_info; mbedtls_md_context_t md_ctx; + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && + hashlen == 0 ) || + hash != NULL ); + RSA_VALIDATE_RET( sig != NULL ); if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 ) return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); @@ -1550,10 +1800,20 @@ int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx, return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); hlen = mbedtls_md_get_size( md_info ); - slen = hlen; - if( olen < hlen + slen + 2 ) + /* Calculate the largest possible salt length. Normally this is the hash + * length, which is the maximum length the salt can have. If there is not + * enough room, use the maximum salt length that fits. The constraint is + * that the hash length plus the salt length plus 2 bytes must be at most + * the key length. This complies with FIPS 186-4 §5.5 (e) and RFC 8017 + * (PKCS#1 v2.2) §9.1.1 step 3. */ + min_slen = hlen - 2; + if( olen < hlen + min_slen + 2 ) return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + else if( olen >= hlen + hlen + 2 ) + slen = hlen; + else + slen = olen - hlen - 2; memset( sig, 0, olen ); @@ -1563,7 +1823,7 @@ int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx, /* Note: EMSA-PSS encoding is over the length of N - 1 bits */ msb = mbedtls_mpi_bitlen( &ctx->N ) - 1; - p += olen - hlen * 2 - 2; + p += olen - hlen - slen - 2; *p++ = 0x01; memcpy( p, salt, slen ); p += slen; @@ -1763,6 +2023,14 @@ int mbedtls_rsa_rsassa_pkcs1_v15_sign( mbedtls_rsa_context *ctx, int ret; unsigned char *sig_try = NULL, *verif = NULL; + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && + hashlen == 0 ) || + hash != NULL ); + RSA_VALIDATE_RET( sig != NULL ); + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); @@ -1832,6 +2100,14 @@ int mbedtls_rsa_pkcs1_sign( mbedtls_rsa_context *ctx, const unsigned char *hash, unsigned char *sig ) { + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && + hashlen == 0 ) || + hash != NULL ); + RSA_VALIDATE_RET( sig != NULL ); + switch( ctx->padding ) { #if defined(MBEDTLS_PKCS1_V15) @@ -1878,6 +2154,14 @@ int mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_rsa_context *ctx, mbedtls_md_context_t md_ctx; unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( sig != NULL ); + RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && + hashlen == 0 ) || + hash != NULL ); + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 ) return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); @@ -2006,7 +2290,16 @@ int mbedtls_rsa_rsassa_pss_verify( mbedtls_rsa_context *ctx, const unsigned char *hash, const unsigned char *sig ) { - mbedtls_md_type_t mgf1_hash_id = ( ctx->hash_id != MBEDTLS_MD_NONE ) + mbedtls_md_type_t mgf1_hash_id; + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( sig != NULL ); + RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && + hashlen == 0 ) || + hash != NULL ); + + mgf1_hash_id = ( ctx->hash_id != MBEDTLS_MD_NONE ) ? (mbedtls_md_type_t) ctx->hash_id : md_alg; @@ -2032,9 +2325,19 @@ int mbedtls_rsa_rsassa_pkcs1_v15_verify( mbedtls_rsa_context *ctx, const unsigned char *sig ) { int ret = 0; - const size_t sig_len = ctx->len; + size_t sig_len; unsigned char *encoded = NULL, *encoded_expected = NULL; + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( sig != NULL ); + RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && + hashlen == 0 ) || + hash != NULL ); + + sig_len = ctx->len; + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); @@ -2104,6 +2407,14 @@ int mbedtls_rsa_pkcs1_verify( mbedtls_rsa_context *ctx, const unsigned char *hash, const unsigned char *sig ) { + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( sig != NULL ); + RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && + hashlen == 0 ) || + hash != NULL ); + switch( ctx->padding ) { #if defined(MBEDTLS_PKCS1_V15) @@ -2129,6 +2440,8 @@ int mbedtls_rsa_pkcs1_verify( mbedtls_rsa_context *ctx, int mbedtls_rsa_copy( mbedtls_rsa_context *dst, const mbedtls_rsa_context *src ) { int ret; + RSA_VALIDATE_RET( dst != NULL ); + RSA_VALIDATE_RET( src != NULL ); dst->ver = src->ver; dst->len = src->len; @@ -2168,14 +2481,23 @@ cleanup: */ void mbedtls_rsa_free( mbedtls_rsa_context *ctx ) { - mbedtls_mpi_free( &ctx->Vi ); mbedtls_mpi_free( &ctx->Vf ); - mbedtls_mpi_free( &ctx->RN ); mbedtls_mpi_free( &ctx->D ); - mbedtls_mpi_free( &ctx->Q ); mbedtls_mpi_free( &ctx->P ); - mbedtls_mpi_free( &ctx->E ); mbedtls_mpi_free( &ctx->N ); + if( ctx == NULL ) + return; + + mbedtls_mpi_free( &ctx->Vi ); + mbedtls_mpi_free( &ctx->Vf ); + mbedtls_mpi_free( &ctx->RN ); + mbedtls_mpi_free( &ctx->D ); + mbedtls_mpi_free( &ctx->Q ); + mbedtls_mpi_free( &ctx->P ); + mbedtls_mpi_free( &ctx->E ); + mbedtls_mpi_free( &ctx->N ); #if !defined(MBEDTLS_RSA_NO_CRT) - mbedtls_mpi_free( &ctx->RQ ); mbedtls_mpi_free( &ctx->RP ); - mbedtls_mpi_free( &ctx->QP ); mbedtls_mpi_free( &ctx->DQ ); + mbedtls_mpi_free( &ctx->RQ ); + mbedtls_mpi_free( &ctx->RP ); + mbedtls_mpi_free( &ctx->QP ); + mbedtls_mpi_free( &ctx->DQ ); mbedtls_mpi_free( &ctx->DP ); #endif /* MBEDTLS_RSA_NO_CRT */ diff --git a/thirdparty/mbedtls/library/rsa_internal.c b/thirdparty/mbedtls/library/rsa_internal.c index 507009f131..9a42d47ceb 100644 --- a/thirdparty/mbedtls/library/rsa_internal.c +++ b/thirdparty/mbedtls/library/rsa_internal.c @@ -351,15 +351,20 @@ int mbedtls_rsa_validate_params( const mbedtls_mpi *N, const mbedtls_mpi *P, */ #if defined(MBEDTLS_GENPRIME) + /* + * When generating keys, the strongest security we support aims for an error + * rate of at most 2^-100 and we are aiming for the same certainty here as + * well. + */ if( f_rng != NULL && P != NULL && - ( ret = mbedtls_mpi_is_prime( P, f_rng, p_rng ) ) != 0 ) + ( ret = mbedtls_mpi_is_prime_ext( P, 50, f_rng, p_rng ) ) != 0 ) { ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; goto cleanup; } if( f_rng != NULL && Q != NULL && - ( ret = mbedtls_mpi_is_prime( Q, f_rng, p_rng ) ) != 0 ) + ( ret = mbedtls_mpi_is_prime_ext( Q, 50, f_rng, p_rng ) ) != 0 ) { ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; goto cleanup; diff --git a/thirdparty/mbedtls/library/sha1.c b/thirdparty/mbedtls/library/sha1.c index bab6087c4e..e8d4096fbb 100644 --- a/thirdparty/mbedtls/library/sha1.c +++ b/thirdparty/mbedtls/library/sha1.c @@ -46,6 +46,11 @@ #endif /* MBEDTLS_PLATFORM_C */ #endif /* MBEDTLS_SELF_TEST */ +#define SHA1_VALIDATE_RET(cond) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_SHA1_BAD_INPUT_DATA ) + +#define SHA1_VALIDATE(cond) MBEDTLS_INTERNAL_VALIDATE( cond ) + #if !defined(MBEDTLS_SHA1_ALT) /* @@ -73,6 +78,8 @@ void mbedtls_sha1_init( mbedtls_sha1_context *ctx ) { + SHA1_VALIDATE( ctx != NULL ); + memset( ctx, 0, sizeof( mbedtls_sha1_context ) ); } @@ -87,6 +94,9 @@ void mbedtls_sha1_free( mbedtls_sha1_context *ctx ) void mbedtls_sha1_clone( mbedtls_sha1_context *dst, const mbedtls_sha1_context *src ) { + SHA1_VALIDATE( dst != NULL ); + SHA1_VALIDATE( src != NULL ); + *dst = *src; } @@ -95,6 +105,8 @@ void mbedtls_sha1_clone( mbedtls_sha1_context *dst, */ int mbedtls_sha1_starts_ret( mbedtls_sha1_context *ctx ) { + SHA1_VALIDATE_RET( ctx != NULL ); + ctx->total[0] = 0; ctx->total[1] = 0; @@ -120,6 +132,9 @@ int mbedtls_internal_sha1_process( mbedtls_sha1_context *ctx, { uint32_t temp, W[16], A, B, C, D, E; + SHA1_VALIDATE_RET( ctx != NULL ); + SHA1_VALIDATE_RET( (const unsigned char *)data != NULL ); + GET_UINT32_BE( W[ 0], data, 0 ); GET_UINT32_BE( W[ 1], data, 4 ); GET_UINT32_BE( W[ 2], data, 8 ); @@ -294,6 +309,9 @@ int mbedtls_sha1_update_ret( mbedtls_sha1_context *ctx, size_t fill; uint32_t left; + SHA1_VALIDATE_RET( ctx != NULL ); + SHA1_VALIDATE_RET( ilen == 0 || input != NULL ); + if( ilen == 0 ) return( 0 ); @@ -352,6 +370,9 @@ int mbedtls_sha1_finish_ret( mbedtls_sha1_context *ctx, uint32_t used; uint32_t high, low; + SHA1_VALIDATE_RET( ctx != NULL ); + SHA1_VALIDATE_RET( (unsigned char *)output != NULL ); + /* * Add padding: 0x80 then 0x00 until 8 bytes remain for the length */ @@ -420,6 +441,9 @@ int mbedtls_sha1_ret( const unsigned char *input, int ret; mbedtls_sha1_context ctx; + SHA1_VALIDATE_RET( ilen == 0 || input != NULL ); + SHA1_VALIDATE_RET( (unsigned char *)output != NULL ); + mbedtls_sha1_init( &ctx ); if( ( ret = mbedtls_sha1_starts_ret( &ctx ) ) != 0 ) diff --git a/thirdparty/mbedtls/library/sha256.c b/thirdparty/mbedtls/library/sha256.c index dbb4a89861..8a540adfbe 100644 --- a/thirdparty/mbedtls/library/sha256.c +++ b/thirdparty/mbedtls/library/sha256.c @@ -49,6 +49,10 @@ #endif /* MBEDTLS_PLATFORM_C */ #endif /* MBEDTLS_SELF_TEST */ +#define SHA256_VALIDATE_RET(cond) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_SHA256_BAD_INPUT_DATA ) +#define SHA256_VALIDATE(cond) MBEDTLS_INTERNAL_VALIDATE( cond ) + #if !defined(MBEDTLS_SHA256_ALT) /* @@ -76,6 +80,8 @@ do { \ void mbedtls_sha256_init( mbedtls_sha256_context *ctx ) { + SHA256_VALIDATE( ctx != NULL ); + memset( ctx, 0, sizeof( mbedtls_sha256_context ) ); } @@ -90,6 +96,9 @@ void mbedtls_sha256_free( mbedtls_sha256_context *ctx ) void mbedtls_sha256_clone( mbedtls_sha256_context *dst, const mbedtls_sha256_context *src ) { + SHA256_VALIDATE( dst != NULL ); + SHA256_VALIDATE( src != NULL ); + *dst = *src; } @@ -98,6 +107,9 @@ void mbedtls_sha256_clone( mbedtls_sha256_context *dst, */ int mbedtls_sha256_starts_ret( mbedtls_sha256_context *ctx, int is224 ) { + SHA256_VALIDATE_RET( ctx != NULL ); + SHA256_VALIDATE_RET( is224 == 0 || is224 == 1 ); + ctx->total[0] = 0; ctx->total[1] = 0; @@ -192,6 +204,9 @@ int mbedtls_internal_sha256_process( mbedtls_sha256_context *ctx, uint32_t A[8]; unsigned int i; + SHA256_VALIDATE_RET( ctx != NULL ); + SHA256_VALIDATE_RET( (const unsigned char *)data != NULL ); + for( i = 0; i < 8; i++ ) A[i] = ctx->state[i]; @@ -263,6 +278,9 @@ int mbedtls_sha256_update_ret( mbedtls_sha256_context *ctx, size_t fill; uint32_t left; + SHA256_VALIDATE_RET( ctx != NULL ); + SHA256_VALIDATE_RET( ilen == 0 || input != NULL ); + if( ilen == 0 ) return( 0 ); @@ -321,6 +339,9 @@ int mbedtls_sha256_finish_ret( mbedtls_sha256_context *ctx, uint32_t used; uint32_t high, low; + SHA256_VALIDATE_RET( ctx != NULL ); + SHA256_VALIDATE_RET( (unsigned char *)output != NULL ); + /* * Add padding: 0x80 then 0x00 until 8 bytes remain for the length */ @@ -395,6 +416,10 @@ int mbedtls_sha256_ret( const unsigned char *input, int ret; mbedtls_sha256_context ctx; + SHA256_VALIDATE_RET( is224 == 0 || is224 == 1 ); + SHA256_VALIDATE_RET( ilen == 0 || input != NULL ); + SHA256_VALIDATE_RET( (unsigned char *)output != NULL ); + mbedtls_sha256_init( &ctx ); if( ( ret = mbedtls_sha256_starts_ret( &ctx, is224 ) ) != 0 ) diff --git a/thirdparty/mbedtls/library/sha512.c b/thirdparty/mbedtls/library/sha512.c index a9440e8af5..941ecda762 100644 --- a/thirdparty/mbedtls/library/sha512.c +++ b/thirdparty/mbedtls/library/sha512.c @@ -55,6 +55,10 @@ #endif /* MBEDTLS_PLATFORM_C */ #endif /* MBEDTLS_SELF_TEST */ +#define SHA512_VALIDATE_RET(cond) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_SHA512_BAD_INPUT_DATA ) +#define SHA512_VALIDATE(cond) MBEDTLS_INTERNAL_VALIDATE( cond ) + #if !defined(MBEDTLS_SHA512_ALT) /* @@ -90,6 +94,8 @@ void mbedtls_sha512_init( mbedtls_sha512_context *ctx ) { + SHA512_VALIDATE( ctx != NULL ); + memset( ctx, 0, sizeof( mbedtls_sha512_context ) ); } @@ -104,6 +110,9 @@ void mbedtls_sha512_free( mbedtls_sha512_context *ctx ) void mbedtls_sha512_clone( mbedtls_sha512_context *dst, const mbedtls_sha512_context *src ) { + SHA512_VALIDATE( dst != NULL ); + SHA512_VALIDATE( src != NULL ); + *dst = *src; } @@ -112,6 +121,9 @@ void mbedtls_sha512_clone( mbedtls_sha512_context *dst, */ int mbedtls_sha512_starts_ret( mbedtls_sha512_context *ctx, int is384 ) { + SHA512_VALIDATE_RET( ctx != NULL ); + SHA512_VALIDATE_RET( is384 == 0 || is384 == 1 ); + ctx->total[0] = 0; ctx->total[1] = 0; @@ -209,6 +221,9 @@ int mbedtls_internal_sha512_process( mbedtls_sha512_context *ctx, uint64_t temp1, temp2, W[80]; uint64_t A, B, C, D, E, F, G, H; + SHA512_VALIDATE_RET( ctx != NULL ); + SHA512_VALIDATE_RET( (const unsigned char *)data != NULL ); + #define SHR(x,n) (x >> n) #define ROTR(x,n) (SHR(x,n) | (x << (64 - n))) @@ -294,6 +309,9 @@ int mbedtls_sha512_update_ret( mbedtls_sha512_context *ctx, size_t fill; unsigned int left; + SHA512_VALIDATE_RET( ctx != NULL ); + SHA512_VALIDATE_RET( ilen == 0 || input != NULL ); + if( ilen == 0 ) return( 0 ); @@ -351,6 +369,9 @@ int mbedtls_sha512_finish_ret( mbedtls_sha512_context *ctx, unsigned used; uint64_t high, low; + SHA512_VALIDATE_RET( ctx != NULL ); + SHA512_VALIDATE_RET( (unsigned char *)output != NULL ); + /* * Add padding: 0x80 then 0x00 until 16 bytes remain for the length */ @@ -427,6 +448,10 @@ int mbedtls_sha512_ret( const unsigned char *input, int ret; mbedtls_sha512_context ctx; + SHA512_VALIDATE_RET( is384 == 0 || is384 == 1 ); + SHA512_VALIDATE_RET( ilen == 0 || input != NULL ); + SHA512_VALIDATE_RET( (unsigned char *)output != NULL ); + mbedtls_sha512_init( &ctx ); if( ( ret = mbedtls_sha512_starts_ret( &ctx, is384 ) ) != 0 ) diff --git a/thirdparty/mbedtls/library/ssl_ciphersuites.c b/thirdparty/mbedtls/library/ssl_ciphersuites.c index 59cdc7a806..745474effe 100644 --- a/thirdparty/mbedtls/library/ssl_ciphersuites.c +++ b/thirdparty/mbedtls/library/ssl_ciphersuites.c @@ -2320,7 +2320,8 @@ mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_alg( const mbedtls_ssl_ciphers #endif /* MBEDTLS_PK_C */ -#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) int mbedtls_ssl_ciphersuite_uses_ec( const mbedtls_ssl_ciphersuite_t *info ) { switch( info->key_exchange ) @@ -2330,13 +2331,14 @@ int mbedtls_ssl_ciphersuite_uses_ec( const mbedtls_ssl_ciphersuite_t *info ) case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: + case MBEDTLS_KEY_EXCHANGE_ECJPAKE: return( 1 ); default: return( 0 ); } } -#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C */ +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED*/ #if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) int mbedtls_ssl_ciphersuite_uses_psk( const mbedtls_ssl_ciphersuite_t *info ) diff --git a/thirdparty/mbedtls/library/ssl_cli.c b/thirdparty/mbedtls/library/ssl_cli.c index ba59c48989..afced7a99c 100644 --- a/thirdparty/mbedtls/library/ssl_cli.c +++ b/thirdparty/mbedtls/library/ssl_cli.c @@ -766,6 +766,10 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl ) unsigned char offer_compress; const int *ciphersuites; const mbedtls_ssl_ciphersuite_t *ciphersuite_info; +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + int uses_ec = 0; +#endif MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write client hello" ) ); @@ -917,6 +921,11 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl ) MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, add ciphersuite: %04x", ciphersuites[i] ) ); +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + uses_ec |= mbedtls_ssl_ciphersuite_uses_ec( ciphersuite_info ); +#endif + n++; *p++ = (unsigned char)( ciphersuites[i] >> 8 ); *p++ = (unsigned char)( ciphersuites[i] ); @@ -1010,11 +1019,14 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl ) #if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - ssl_write_supported_elliptic_curves_ext( ssl, p + 2 + ext_len, &olen ); - ext_len += olen; + if( uses_ec ) + { + ssl_write_supported_elliptic_curves_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; - ssl_write_supported_point_formats_ext( ssl, p + 2 + ext_len, &olen ); - ext_len += olen; + ssl_write_supported_point_formats_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; + } #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) @@ -1076,11 +1088,20 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl ) mbedtls_ssl_send_flight_completed( ssl ); #endif - if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); + return( ret ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 ) { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flight_transmit", ret ); return( ret ); } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write client hello" ) ); @@ -1479,7 +1500,7 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) buf = ssl->in_msg; - if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) { /* No alert on a read error. */ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); @@ -1742,6 +1763,14 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %s", suite_info->name ) ); +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA && + ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + ssl->handshake->ecrs_enabled = 1; + } +#endif + if( comp != MBEDTLS_SSL_COMPRESS_NULL #if defined(MBEDTLS_ZLIB_SUPPORT) && comp != MBEDTLS_SSL_COMPRESS_DEFLATE @@ -1998,8 +2027,14 @@ static int ssl_parse_server_dh_params( mbedtls_ssl_context *ssl, unsigned char * static int ssl_check_server_ecdh_params( const mbedtls_ssl_context *ssl ) { const mbedtls_ecp_curve_info *curve_info; + mbedtls_ecp_group_id grp_id; +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + grp_id = ssl->handshake->ecdh_ctx.grp.id; +#else + grp_id = ssl->handshake->ecdh_ctx.grp_id; +#endif - curve_info = mbedtls_ecp_curve_info_from_grp_id( ssl->handshake->ecdh_ctx.grp.id ); + curve_info = mbedtls_ecp_curve_info_from_grp_id( grp_id ); if( curve_info == NULL ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); @@ -2009,14 +2044,15 @@ static int ssl_check_server_ecdh_params( const mbedtls_ssl_context *ssl ) MBEDTLS_SSL_DEBUG_MSG( 2, ( "ECDH curve: %s", curve_info->name ) ); #if defined(MBEDTLS_ECP_C) - if( mbedtls_ssl_check_curve( ssl, ssl->handshake->ecdh_ctx.grp.id ) != 0 ) + if( mbedtls_ssl_check_curve( ssl, grp_id ) != 0 ) #else if( ssl->handshake->ecdh_ctx.grp.nbits < 163 || ssl->handshake->ecdh_ctx.grp.nbits > 521 ) #endif return( -1 ); - MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Qp", &ssl->handshake->ecdh_ctx.Qp ); + MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, + MBEDTLS_DEBUG_ECDH_QP ); return( 0 ); } @@ -2047,6 +2083,10 @@ static int ssl_parse_server_ecdh_params( mbedtls_ssl_context *ssl, (const unsigned char **) p, end ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ecdh_read_params" ), ret ); +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS; +#endif return( ret ); } @@ -2076,7 +2116,7 @@ static int ssl_parse_server_psk_hint( mbedtls_ssl_context *ssl, * * opaque psk_identity_hint<0..2^16-1>; */ - if( (*p) > end - 2 ) + if( end - (*p) < 2 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message " "(psk_identity_hint length)" ) ); @@ -2085,7 +2125,7 @@ static int ssl_parse_server_psk_hint( mbedtls_ssl_context *ssl, len = (*p)[0] << 8 | (*p)[1]; *p += 2; - if( (*p) > end - len ) + if( end - (*p) < (int) len ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message " "(psk_identity_hint length)" ) ); @@ -2328,7 +2368,15 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) #endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED || MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ - if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ssl->handshake->ecrs_enabled && + ssl->handshake->ecrs_state == ssl_ecrs_ske_start_processing ) + { + goto start_processing; + } +#endif + + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); return( ret ); @@ -2365,6 +2413,12 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); } +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ssl->handshake->ecrs_enabled ) + ssl->handshake->ecrs_state = ssl_ecrs_ske_start_processing; + +start_processing: +#endif p = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ); end = ssl->in_msg + ssl->in_hslen; MBEDTLS_SSL_DEBUG_BUF( 3, "server key exchange", p, end - p ); @@ -2457,6 +2511,7 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; unsigned char *params = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ); size_t params_len = p - params; + void *rs_ctx = NULL; /* * Handle the digitally-signed structure @@ -2579,12 +2634,25 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH ); } - if( ( ret = mbedtls_pk_verify( &ssl->session_negotiate->peer_cert->pk, - md_alg, hash, hashlen, p, sig_len ) ) != 0 ) +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ssl->handshake->ecrs_enabled ) + rs_ctx = &ssl->handshake->ecrs_ctx.pk; +#endif + + if( ( ret = mbedtls_pk_verify_restartable( + &ssl->session_negotiate->peer_cert->pk, + md_alg, hash, hashlen, p, sig_len, rs_ctx ) ) != 0 ) { - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR ); +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) +#endif + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR ); MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_verify", ret ); +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS; +#endif return( ret ); } } @@ -2635,7 +2703,7 @@ static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl ) return( 0 ); } - if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); return( ret ); @@ -2709,7 +2777,7 @@ static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl ) * therefore the buffer length at this point must be greater than that * regardless of the actual code path. */ - if( ssl->in_hslen <= mbedtls_ssl_hs_hdr_len( ssl ) + 3 + n ) + if( ssl->in_hslen <= mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, @@ -2787,7 +2855,7 @@ static int ssl_parse_server_hello_done( mbedtls_ssl_context *ssl ) MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse server hello done" ) ); - if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); return( ret ); @@ -2882,6 +2950,16 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl ) */ i = 4; +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ssl->handshake->ecrs_enabled ) + { + if( ssl->handshake->ecrs_state == ssl_ecrs_cke_ecdh_calc_secret ) + goto ecdh_calc_secret; + + mbedtls_ecdh_enable_restart( &ssl->handshake->ecdh_ctx ); + } +#endif + ret = mbedtls_ecdh_make_public( &ssl->handshake->ecdh_ctx, &n, &ssl->out_msg[i], 1000, @@ -2889,11 +2967,27 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl ) if( ret != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_make_public", ret ); +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS; +#endif return( ret ); } - MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Q", &ssl->handshake->ecdh_ctx.Q ); + MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, + MBEDTLS_DEBUG_ECDH_Q ); + +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ssl->handshake->ecrs_enabled ) + { + ssl->handshake->ecrs_n = n; + ssl->handshake->ecrs_state = ssl_ecrs_cke_ecdh_calc_secret; + } +ecdh_calc_secret: + if( ssl->handshake->ecrs_enabled ) + n = ssl->handshake->ecrs_n; +#endif if( ( ret = mbedtls_ecdh_calc_secret( &ssl->handshake->ecdh_ctx, &ssl->handshake->pmslen, ssl->handshake->premaster, @@ -2901,10 +2995,15 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl ) ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_calc_secret", ret ); +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS; +#endif return( ret ); } - MBEDTLS_SSL_DEBUG_MPI( 3, "ECDH: z", &ssl->handshake->ecdh_ctx.z ); + MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, + MBEDTLS_DEBUG_ECDH_Z ); } else #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || @@ -2999,7 +3098,8 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl ) return( ret ); } - MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Q", &ssl->handshake->ecdh_ctx.Q ); + MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, + MBEDTLS_DEBUG_ECDH_Q ); } else #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ @@ -3063,9 +3163,9 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl ) ssl->state++; - if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); return( ret ); } @@ -3119,9 +3219,18 @@ static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl ) unsigned char *hash_start = hash; mbedtls_md_type_t md_alg = MBEDTLS_MD_NONE; unsigned int hashlen; + void *rs_ctx = NULL; MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate verify" ) ); +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ssl->handshake->ecrs_enabled && + ssl->handshake->ecrs_state == ssl_ecrs_crt_vrfy_sign ) + { + goto sign; + } +#endif + if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret ); @@ -3153,8 +3262,15 @@ static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl ) } /* - * Make an RSA signature of the handshake digests + * Make a signature of the handshake digests */ +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ssl->handshake->ecrs_enabled ) + ssl->handshake->ecrs_state = ssl_ecrs_crt_vrfy_sign; + +sign: +#endif + ssl->handshake->calc_verify( ssl, hash ); #if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ @@ -3231,11 +3347,21 @@ static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl ) return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); } - if( ( ret = mbedtls_pk_sign( mbedtls_ssl_own_key( ssl ), md_alg, hash_start, hashlen, +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ssl->handshake->ecrs_enabled ) + rs_ctx = &ssl->handshake->ecrs_ctx.pk; +#endif + + if( ( ret = mbedtls_pk_sign_restartable( mbedtls_ssl_own_key( ssl ), + md_alg, hash_start, hashlen, ssl->out_msg + 6 + offset, &n, - ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + ssl->conf->f_rng, ssl->conf->p_rng, rs_ctx ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_sign", ret ); +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS; +#endif return( ret ); } @@ -3248,9 +3374,9 @@ static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl ) ssl->state++; - if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); return( ret ); } @@ -3276,7 +3402,7 @@ static int ssl_parse_new_session_ticket( mbedtls_ssl_context *ssl ) MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse new session ticket" ) ); - if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); return( ret ); @@ -3311,8 +3437,8 @@ static int ssl_parse_new_session_ticket( mbedtls_ssl_context *ssl ) msg = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ); - lifetime = ( msg[0] << 24 ) | ( msg[1] << 16 ) | - ( msg[2] << 8 ) | ( msg[3] ); + lifetime = ( ((uint32_t) msg[0]) << 24 ) | ( msg[1] << 16 ) | + ( msg[2] << 8 ) | ( msg[3] ); ticket_len = ( msg[4] << 8 ) | ( msg[5] ); @@ -3390,10 +3516,10 @@ int mbedtls_ssl_handshake_client_step( mbedtls_ssl_context *ssl ) if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING ) { - if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 ) + if( ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 ) return( ret ); } -#endif +#endif /* MBEDTLS_SSL_PROTO_DTLS */ /* Change state now, so that it is right in mbedtls_ssl_read_record(), used * by DTLS for dropping out-of-sequence ChangeCipherSpec records */ diff --git a/thirdparty/mbedtls/library/ssl_srv.c b/thirdparty/mbedtls/library/ssl_srv.c index 52087ae6e1..bc77f80203 100644 --- a/thirdparty/mbedtls/library/ssl_srv.c +++ b/thirdparty/mbedtls/library/ssl_srv.c @@ -1294,7 +1294,7 @@ read_record_header: return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } - memcpy( ssl->out_ctr + 2, ssl->in_ctr + 2, 6 ); + memcpy( ssl->cur_out_ctr + 2, ssl->in_ctr + 2, 6 ); #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) if( mbedtls_ssl_dtls_replay_check( ssl ) != 0 ) @@ -2384,12 +2384,21 @@ static int ssl_write_hello_verify_request( mbedtls_ssl_context *ssl ) ssl->state = MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT; - if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); return( ret ); } +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flight_transmit", ret ); + return( ret ); + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write hello verify request" ) ); return( 0 ); @@ -2589,8 +2598,12 @@ static int ssl_write_server_hello( mbedtls_ssl_context *ssl ) #if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - ssl_write_supported_point_formats_ext( ssl, p + 2 + ext_len, &olen ); - ext_len += olen; + if ( mbedtls_ssl_ciphersuite_uses_ec( + mbedtls_ssl_ciphersuite_from_id( ssl->session_negotiate->ciphersuite ) ) ) + { + ssl_write_supported_point_formats_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; + } #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) @@ -2620,7 +2633,7 @@ static int ssl_write_server_hello( mbedtls_ssl_context *ssl ) ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; ssl->out_msg[0] = MBEDTLS_SSL_HS_SERVER_HELLO; - ret = mbedtls_ssl_write_record( ssl ); + ret = mbedtls_ssl_write_handshake_msg( ssl ); MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server hello" ) ); @@ -2815,7 +2828,7 @@ static int ssl_write_certificate_request( mbedtls_ssl_context *ssl ) ssl->out_msg[4 + ct_len + sa_len] = (unsigned char)( total_dn_size >> 8 ); ssl->out_msg[5 + ct_len + sa_len] = (unsigned char)( total_dn_size ); - ret = mbedtls_ssl_write_record( ssl ); + ret = mbedtls_ssl_write_handshake_msg( ssl ); MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write certificate request" ) ); @@ -3035,8 +3048,8 @@ curve_matching_done: MBEDTLS_SSL_DEBUG_MSG( 2, ( "ECDHE curve: %s", (*curve)->name ) ); - if( ( ret = mbedtls_ecp_group_load( &ssl->handshake->ecdh_ctx.grp, - (*curve)->grp_id ) ) != 0 ) + if( ( ret = mbedtls_ecdh_setup( &ssl->handshake->ecdh_ctx, + (*curve)->grp_id ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecp_group_load", ret ); return( ret ); @@ -3058,7 +3071,8 @@ curve_matching_done: ssl->out_msglen += len; - MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Q ", &ssl->handshake->ecdh_ctx.Q ); + MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, + MBEDTLS_DEBUG_ECDH_Q ); } #endif /* MBEDTLS_KEY_EXCHANGE__SOME__ECDHE_ENABLED */ @@ -3332,9 +3346,9 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl ) ssl->state++; - if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); return( ret ); } @@ -3359,11 +3373,20 @@ static int ssl_write_server_hello_done( mbedtls_ssl_context *ssl ) mbedtls_ssl_send_flight_completed( ssl ); #endif - if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); + return( ret ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 ) { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flight_transmit", ret ); return( ret ); } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server hello done" ) ); @@ -3706,7 +3729,7 @@ static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl ) } else #endif - if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); return( ret ); @@ -3772,7 +3795,8 @@ static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl ) return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP ); } - MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Qp ", &ssl->handshake->ecdh_ctx.Qp ); + MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, + MBEDTLS_DEBUG_ECDH_QP ); if( ( ret = mbedtls_ecdh_calc_secret( &ssl->handshake->ecdh_ctx, &ssl->handshake->pmslen, @@ -3784,7 +3808,8 @@ static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl ) return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS ); } - MBEDTLS_SSL_DEBUG_MPI( 3, "ECDH: z ", &ssl->handshake->ecdh_ctx.z ); + MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, + MBEDTLS_DEBUG_ECDH_Z ); } else #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || @@ -3897,7 +3922,8 @@ static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl ) return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP ); } - MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Qp ", &ssl->handshake->ecdh_ctx.Qp ); + MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, + MBEDTLS_DEBUG_ECDH_QP ); if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl, ciphersuite_info->key_exchange ) ) != 0 ) @@ -4016,25 +4042,10 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl ) } /* Read the message without adding it to the checksum */ - do { - - do ret = mbedtls_ssl_read_record_layer( ssl ); - while( ret == MBEDTLS_ERR_SSL_CONTINUE_PROCESSING ); - - if( ret != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_read_record_layer" ), ret ); - return( ret ); - } - - ret = mbedtls_ssl_handle_message_type( ssl ); - - } while( MBEDTLS_ERR_SSL_NON_FATAL == ret || - MBEDTLS_ERR_SSL_CONTINUE_PROCESSING == ret ); - + ret = mbedtls_ssl_read_record( ssl, 0 /* no checksum update */ ); if( 0 != ret ) { - MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_handle_message_type" ), ret ); + MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_read_record" ), ret ); return( ret ); } @@ -4223,9 +4234,9 @@ static int ssl_write_new_session_ticket( mbedtls_ssl_context *ssl ) */ ssl->handshake->new_session_ticket = 0; - if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); return( ret ); } @@ -4254,10 +4265,10 @@ int mbedtls_ssl_handshake_server_step( mbedtls_ssl_context *ssl ) if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING ) { - if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 ) + if( ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 ) return( ret ); } -#endif +#endif /* MBEDTLS_SSL_PROTO_DTLS */ switch( ssl->state ) { diff --git a/thirdparty/mbedtls/library/ssl_ticket.c b/thirdparty/mbedtls/library/ssl_ticket.c index a2b304869e..8492c19a8c 100644 --- a/thirdparty/mbedtls/library/ssl_ticket.c +++ b/thirdparty/mbedtls/library/ssl_ticket.c @@ -97,7 +97,7 @@ static int ssl_ticket_update_keys( mbedtls_ssl_ticket_context *ctx ) uint32_t current_time = (uint32_t) mbedtls_time( NULL ); uint32_t key_time = ctx->keys[ctx->active].generation_time; - if( current_time > key_time && + if( current_time >= key_time && current_time - key_time < ctx->ticket_lifetime ) { return( 0 ); @@ -188,9 +188,9 @@ static int ssl_save_session( const mbedtls_ssl_session *session, if( left < 3 + cert_len ) return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); - *p++ = (unsigned char)( cert_len >> 16 & 0xFF ); - *p++ = (unsigned char)( cert_len >> 8 & 0xFF ); - *p++ = (unsigned char)( cert_len & 0xFF ); + *p++ = (unsigned char)( ( cert_len >> 16 ) & 0xFF ); + *p++ = (unsigned char)( ( cert_len >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( cert_len ) & 0xFF ); if( session->peer_cert != NULL ) memcpy( p, session->peer_cert->raw.p, cert_len ); @@ -215,14 +215,14 @@ static int ssl_load_session( mbedtls_ssl_session *session, size_t cert_len; #endif /* MBEDTLS_X509_CRT_PARSE_C */ - if( p + sizeof( mbedtls_ssl_session ) > end ) + if( sizeof( mbedtls_ssl_session ) > (size_t)( end - p ) ) return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); memcpy( session, p, sizeof( mbedtls_ssl_session ) ); p += sizeof( mbedtls_ssl_session ); #if defined(MBEDTLS_X509_CRT_PARSE_C) - if( p + 3 > end ) + if( 3 > (size_t)( end - p ) ) return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); cert_len = ( p[0] << 16 ) | ( p[1] << 8 ) | p[2]; @@ -236,7 +236,7 @@ static int ssl_load_session( mbedtls_ssl_session *session, { int ret; - if( p + cert_len > end ) + if( cert_len > (size_t)( end - p ) ) return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); session->peer_cert = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) ); @@ -247,7 +247,7 @@ static int ssl_load_session( mbedtls_ssl_session *session, mbedtls_x509_crt_init( session->peer_cert ); if( ( ret = mbedtls_x509_crt_parse_der( session->peer_cert, - p, cert_len ) ) != 0 ) + p, cert_len ) ) != 0 ) { mbedtls_x509_crt_free( session->peer_cert ); mbedtls_free( session->peer_cert ); diff --git a/thirdparty/mbedtls/library/ssl_tls.c b/thirdparty/mbedtls/library/ssl_tls.c index 91f96c8ab6..38690fa664 100644 --- a/thirdparty/mbedtls/library/ssl_tls.c +++ b/thirdparty/mbedtls/library/ssl_tls.c @@ -54,6 +54,9 @@ #include "mbedtls/oid.h" #endif +static void ssl_reset_in_out_pointers( mbedtls_ssl_context *ssl ); +static uint32_t ssl_get_hs_total_len( mbedtls_ssl_context const *ssl ); + /* Length of the "epoch" field in the record header */ static inline size_t ssl_ep_len( const mbedtls_ssl_context *ssl ) { @@ -96,7 +99,101 @@ static int ssl_check_timer( mbedtls_ssl_context *ssl ) return( 0 ); } +static void ssl_update_out_pointers( mbedtls_ssl_context *ssl, + mbedtls_ssl_transform *transform ); +static void ssl_update_in_pointers( mbedtls_ssl_context *ssl, + mbedtls_ssl_transform *transform ); + +#define SSL_DONT_FORCE_FLUSH 0 +#define SSL_FORCE_FLUSH 1 + #if defined(MBEDTLS_SSL_PROTO_DTLS) + +/* Forward declarations for functions related to message buffering. */ +static void ssl_buffering_free( mbedtls_ssl_context *ssl ); +static void ssl_buffering_free_slot( mbedtls_ssl_context *ssl, + uint8_t slot ); +static void ssl_free_buffered_record( mbedtls_ssl_context *ssl ); +static int ssl_load_buffered_message( mbedtls_ssl_context *ssl ); +static int ssl_load_buffered_record( mbedtls_ssl_context *ssl ); +static int ssl_buffer_message( mbedtls_ssl_context *ssl ); +static int ssl_buffer_future_record( mbedtls_ssl_context *ssl ); +static int ssl_next_record_is_in_datagram( mbedtls_ssl_context *ssl ); + +static size_t ssl_get_current_mtu( const mbedtls_ssl_context *ssl ); +static size_t ssl_get_maximum_datagram_size( mbedtls_ssl_context const *ssl ) +{ + size_t mtu = ssl_get_current_mtu( ssl ); + + if( mtu != 0 && mtu < MBEDTLS_SSL_OUT_BUFFER_LEN ) + return( mtu ); + + return( MBEDTLS_SSL_OUT_BUFFER_LEN ); +} + +static int ssl_get_remaining_space_in_datagram( mbedtls_ssl_context const *ssl ) +{ + size_t const bytes_written = ssl->out_left; + size_t const mtu = ssl_get_maximum_datagram_size( ssl ); + + /* Double-check that the write-index hasn't gone + * past what we can transmit in a single datagram. */ + if( bytes_written > mtu ) + { + /* Should never happen... */ + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + return( (int) ( mtu - bytes_written ) ); +} + +static int ssl_get_remaining_payload_in_datagram( mbedtls_ssl_context const *ssl ) +{ + int ret; + size_t remaining, expansion; + size_t max_len = MBEDTLS_SSL_OUT_CONTENT_LEN; + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + const size_t mfl = mbedtls_ssl_get_max_frag_len( ssl ); + + if( max_len > mfl ) + max_len = mfl; + + /* By the standard (RFC 6066 Sect. 4), the MFL extension + * only limits the maximum record payload size, so in theory + * we would be allowed to pack multiple records of payload size + * MFL into a single datagram. However, this would mean that there's + * no way to explicitly communicate MTU restrictions to the peer. + * + * The following reduction of max_len makes sure that we never + * write datagrams larger than MFL + Record Expansion Overhead. + */ + if( max_len <= ssl->out_left ) + return( 0 ); + + max_len -= ssl->out_left; +#endif + + ret = ssl_get_remaining_space_in_datagram( ssl ); + if( ret < 0 ) + return( ret ); + remaining = (size_t) ret; + + ret = mbedtls_ssl_get_record_expansion( ssl ); + if( ret < 0 ) + return( ret ); + expansion = (size_t) ret; + + if( remaining <= expansion ) + return( 0 ); + + remaining -= expansion; + if( remaining >= max_len ) + remaining = max_len; + + return( (int) remaining ); +} + /* * Double the retransmit timeout value, within the allowed range, * returning -1 if the maximum value has already been reached. @@ -108,6 +205,18 @@ static int ssl_double_retransmit_timeout( mbedtls_ssl_context *ssl ) if( ssl->handshake->retransmit_timeout >= ssl->conf->hs_timeout_max ) return( -1 ); + /* Implement the final paragraph of RFC 6347 section 4.1.1.1 + * in the following way: after the initial transmission and a first + * retransmission, back off to a temporary estimated MTU of 508 bytes. + * This value is guaranteed to be deliverable (if not guaranteed to be + * delivered) of any compliant IPv4 (and IPv6) network, and should work + * on most non-IP stacks too. */ + if( ssl->handshake->retransmit_timeout != ssl->conf->hs_timeout_min ) + { + ssl->handshake->mtu = 508; + MBEDTLS_SSL_DEBUG_MSG( 2, ( "mtu autoreduction to %d bytes", ssl->handshake->mtu ) ); + } + new_timeout = 2 * ssl->handshake->retransmit_timeout; /* Avoid arithmetic overflow and range overflow */ @@ -1224,7 +1333,8 @@ int mbedtls_ssl_psk_derive_premaster( mbedtls_ssl_context *ssl, mbedtls_key_exch *(p++) = (unsigned char)( zlen ); p += zlen; - MBEDTLS_SSL_DEBUG_MPI( 3, "ECDH: z", &ssl->handshake->ecdh_ctx.z ); + MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, + MBEDTLS_DEBUG_ECDH_Z ); } else #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ @@ -1345,14 +1455,6 @@ static int ssl_encrypt_buf( mbedtls_ssl_context *ssl ) MBEDTLS_SSL_DEBUG_BUF( 4, "before encrypt: output payload", ssl->out_msg, ssl->out_msglen ); - if( ssl->out_msglen > MBEDTLS_SSL_OUT_CONTENT_LEN ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "Record content %u too large, maximum %d", - (unsigned) ssl->out_msglen, - MBEDTLS_SSL_OUT_CONTENT_LEN ) ); - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - } - /* * Add MAC before if needed */ @@ -1626,6 +1728,8 @@ static int ssl_encrypt_buf( mbedtls_ssl_context *ssl ) #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) if( auth_done == 0 ) { + unsigned char mac[MBEDTLS_SSL_MAC_ADD]; + /* * MAC(MAC_write_key, seq_num + * TLSCipherText.type + @@ -1648,10 +1752,12 @@ static int ssl_encrypt_buf( mbedtls_ssl_context *ssl ) mbedtls_md_hmac_update( &ssl->transform_out->md_ctx_enc, pseudo_hdr, 13 ); mbedtls_md_hmac_update( &ssl->transform_out->md_ctx_enc, ssl->out_iv, ssl->out_msglen ); - mbedtls_md_hmac_finish( &ssl->transform_out->md_ctx_enc, - ssl->out_iv + ssl->out_msglen ); + mbedtls_md_hmac_finish( &ssl->transform_out->md_ctx_enc, mac ); mbedtls_md_hmac_reset( &ssl->transform_out->md_ctx_enc ); + memcpy( ssl->out_iv + ssl->out_msglen, mac, + ssl->transform_out->maclen ); + ssl->out_msglen += ssl->transform_out->maclen; auth_done++; } @@ -2202,13 +2308,13 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl ) correct = 0; } auth_done++; - - /* - * Finally check the correct flag - */ - if( correct == 0 ) - return( MBEDTLS_ERR_SSL_INVALID_MAC ); } + + /* + * Finally check the correct flag + */ + if( correct == 0 ) + return( MBEDTLS_ERR_SSL_INVALID_MAC ); #endif /* SSL_SOME_MODES_USE_MAC */ /* Make extra sure authentication was performed, exactly once */ @@ -2644,7 +2750,7 @@ int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want ) int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl ) { int ret; - unsigned char *buf, i; + unsigned char *buf; MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> flush output" ) ); @@ -2667,8 +2773,7 @@ int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl ) MBEDTLS_SSL_DEBUG_MSG( 2, ( "message length: %d, out_left: %d", mbedtls_ssl_hdr_len( ssl ) + ssl->out_msglen, ssl->out_left ) ); - buf = ssl->out_hdr + mbedtls_ssl_hdr_len( ssl ) + - ssl->out_msglen - ssl->out_left; + buf = ssl->out_hdr - ssl->out_left; ret = ssl->f_send( ssl->p_bio, buf, ssl->out_left ); MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_send", ret ); @@ -2687,16 +2792,17 @@ int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl ) ssl->out_left -= ret; } - for( i = 8; i > ssl_ep_len( ssl ); i-- ) - if( ++ssl->out_ctr[i - 1] != 0 ) - break; - - /* The loop goes to its end iff the counter is wrapping */ - if( i == ssl_ep_len( ssl ) ) +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + ssl->out_hdr = ssl->out_buf; + } + else +#endif { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "outgoing message counter would wrap" ) ); - return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING ); + ssl->out_hdr = ssl->out_buf + 8; } + ssl_update_out_pointers( ssl, ssl->transform_out ); MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= flush output" ) ); @@ -2713,6 +2819,9 @@ int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl ) static int ssl_flight_append( mbedtls_ssl_context *ssl ) { mbedtls_ssl_flight_item *msg; + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_flight_append" ) ); + MBEDTLS_SSL_DEBUG_BUF( 4, "message appended to flight", + ssl->out_msg, ssl->out_msglen ); /* Allocate space for current message */ if( ( msg = mbedtls_calloc( 1, sizeof( mbedtls_ssl_flight_item ) ) ) == NULL ) @@ -2746,6 +2855,7 @@ static int ssl_flight_append( mbedtls_ssl_context *ssl ) cur->next = msg; } + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_flight_append" ) ); return( 0 ); } @@ -2794,19 +2904,12 @@ static void ssl_swap_epochs( mbedtls_ssl_context *ssl ) ssl->handshake->alt_transform_out = tmp_transform; /* Swap epoch + sequence_number */ - memcpy( tmp_out_ctr, ssl->out_ctr, 8 ); - memcpy( ssl->out_ctr, ssl->handshake->alt_out_ctr, 8 ); + memcpy( tmp_out_ctr, ssl->cur_out_ctr, 8 ); + memcpy( ssl->cur_out_ctr, ssl->handshake->alt_out_ctr, 8 ); memcpy( ssl->handshake->alt_out_ctr, tmp_out_ctr, 8 ); /* Adjust to the newly activated transform */ - if( ssl->transform_out != NULL && - ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) - { - ssl->out_msg = ssl->out_iv + ssl->transform_out->ivlen - - ssl->transform_out->fixed_ivlen; - } - else - ssl->out_msg = ssl->out_iv; + ssl_update_out_pointers( ssl, ssl->transform_out ); #if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) if( mbedtls_ssl_hw_record_activate != NULL ) @@ -2822,20 +2925,38 @@ static void ssl_swap_epochs( mbedtls_ssl_context *ssl ) /* * Retransmit the current flight of messages. + */ +int mbedtls_ssl_resend( mbedtls_ssl_context *ssl ) +{ + int ret = 0; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> mbedtls_ssl_resend" ) ); + + ret = mbedtls_ssl_flight_transmit( ssl ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= mbedtls_ssl_resend" ) ); + + return( ret ); +} + +/* + * Transmit or retransmit the current flight of messages. * * Need to remember the current message in case flush_output returns * WANT_WRITE, causing us to exit this function and come back later. * This function must be called until state is no longer SENDING. */ -int mbedtls_ssl_resend( mbedtls_ssl_context *ssl ) +int mbedtls_ssl_flight_transmit( mbedtls_ssl_context *ssl ) { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> mbedtls_ssl_resend" ) ); + int ret; + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> mbedtls_ssl_flight_transmit" ) ); if( ssl->handshake->retransmit_state != MBEDTLS_SSL_RETRANS_SENDING ) { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialise resending" ) ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialise flight transmission" ) ); ssl->handshake->cur_msg = ssl->handshake->flight; + ssl->handshake->cur_msg_p = ssl->handshake->flight->p + 12; ssl_swap_epochs( ssl ); ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_SENDING; @@ -2843,33 +2964,129 @@ int mbedtls_ssl_resend( mbedtls_ssl_context *ssl ) while( ssl->handshake->cur_msg != NULL ) { - int ret; - mbedtls_ssl_flight_item *cur = ssl->handshake->cur_msg; + size_t max_frag_len; + const mbedtls_ssl_flight_item * const cur = ssl->handshake->cur_msg; + + int const is_finished = + ( cur->type == MBEDTLS_SSL_MSG_HANDSHAKE && + cur->p[0] == MBEDTLS_SSL_HS_FINISHED ); + + uint8_t const force_flush = ssl->disable_datagram_packing == 1 ? + SSL_FORCE_FLUSH : SSL_DONT_FORCE_FLUSH; /* Swap epochs before sending Finished: we can't do it after * sending ChangeCipherSpec, in case write returns WANT_READ. * Must be done before copying, may change out_msg pointer */ - if( cur->type == MBEDTLS_SSL_MSG_HANDSHAKE && - cur->p[0] == MBEDTLS_SSL_HS_FINISHED ) + if( is_finished && ssl->handshake->cur_msg_p == ( cur->p + 12 ) ) { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "swap epochs to send finished message" ) ); ssl_swap_epochs( ssl ); } - memcpy( ssl->out_msg, cur->p, cur->len ); - ssl->out_msglen = cur->len; - ssl->out_msgtype = cur->type; + ret = ssl_get_remaining_payload_in_datagram( ssl ); + if( ret < 0 ) + return( ret ); + max_frag_len = (size_t) ret; + + /* CCS is copied as is, while HS messages may need fragmentation */ + if( cur->type == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC ) + { + if( max_frag_len == 0 ) + { + if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) + return( ret ); + + continue; + } + + memcpy( ssl->out_msg, cur->p, cur->len ); + ssl->out_msglen = cur->len; + ssl->out_msgtype = cur->type; + + /* Update position inside current message */ + ssl->handshake->cur_msg_p += cur->len; + } + else + { + const unsigned char * const p = ssl->handshake->cur_msg_p; + const size_t hs_len = cur->len - 12; + const size_t frag_off = p - ( cur->p + 12 ); + const size_t rem_len = hs_len - frag_off; + size_t cur_hs_frag_len, max_hs_frag_len; - ssl->handshake->cur_msg = cur->next; + if( ( max_frag_len < 12 ) || ( max_frag_len == 12 && hs_len != 0 ) ) + { + if( is_finished ) + ssl_swap_epochs( ssl ); - MBEDTLS_SSL_DEBUG_BUF( 3, "resent handshake message header", ssl->out_msg, 12 ); + if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) + return( ret ); + + continue; + } + max_hs_frag_len = max_frag_len - 12; + + cur_hs_frag_len = rem_len > max_hs_frag_len ? + max_hs_frag_len : rem_len; + + if( frag_off == 0 && cur_hs_frag_len != hs_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "fragmenting handshake message (%u > %u)", + (unsigned) cur_hs_frag_len, + (unsigned) max_hs_frag_len ) ); + } + + /* Messages are stored with handshake headers as if not fragmented, + * copy beginning of headers then fill fragmentation fields. + * Handshake headers: type(1) len(3) seq(2) f_off(3) f_len(3) */ + memcpy( ssl->out_msg, cur->p, 6 ); + + ssl->out_msg[6] = ( ( frag_off >> 16 ) & 0xff ); + ssl->out_msg[7] = ( ( frag_off >> 8 ) & 0xff ); + ssl->out_msg[8] = ( ( frag_off ) & 0xff ); + + ssl->out_msg[ 9] = ( ( cur_hs_frag_len >> 16 ) & 0xff ); + ssl->out_msg[10] = ( ( cur_hs_frag_len >> 8 ) & 0xff ); + ssl->out_msg[11] = ( ( cur_hs_frag_len ) & 0xff ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "handshake header", ssl->out_msg, 12 ); + + /* Copy the handshake message content and set records fields */ + memcpy( ssl->out_msg + 12, p, cur_hs_frag_len ); + ssl->out_msglen = cur_hs_frag_len + 12; + ssl->out_msgtype = cur->type; + + /* Update position inside current message */ + ssl->handshake->cur_msg_p += cur_hs_frag_len; + } + + /* If done with the current message move to the next one if any */ + if( ssl->handshake->cur_msg_p >= cur->p + cur->len ) + { + if( cur->next != NULL ) + { + ssl->handshake->cur_msg = cur->next; + ssl->handshake->cur_msg_p = cur->next->p + 12; + } + else + { + ssl->handshake->cur_msg = NULL; + ssl->handshake->cur_msg_p = NULL; + } + } - if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + /* Actually send the message out */ + if( ( ret = mbedtls_ssl_write_record( ssl, force_flush ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); return( ret ); } } + if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) + return( ret ); + + /* Update state and set timer */ if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER ) ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED; else @@ -2878,7 +3095,7 @@ int mbedtls_ssl_resend( mbedtls_ssl_context *ssl ) ssl_set_timer( ssl, ssl->handshake->retransmit_timeout ); } - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= mbedtls_ssl_resend" ) ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= mbedtls_ssl_flight_transmit" ) ); return( 0 ); } @@ -2896,6 +3113,12 @@ void mbedtls_ssl_recv_flight_completed( mbedtls_ssl_context *ssl ) /* The next incoming flight will start with this msg_seq */ ssl->handshake->in_flight_start_seq = ssl->handshake->in_msg_seq; + /* We don't want to remember CCS's across flight boundaries. */ + ssl->handshake->buffering.seen_ccs = 0; + + /* Clear future message buffering structure. */ + ssl_buffering_free( ssl ); + /* Cancel timer */ ssl_set_timer( ssl, 0 ); @@ -2927,43 +3150,102 @@ void mbedtls_ssl_send_flight_completed( mbedtls_ssl_context *ssl ) #endif /* MBEDTLS_SSL_PROTO_DTLS */ /* - * Record layer functions + * Handshake layer functions */ /* - * Write current record. - * Uses ssl->out_msgtype, ssl->out_msglen and bytes at ssl->out_msg. + * Write (DTLS: or queue) current handshake (including CCS) message. + * + * - fill in handshake headers + * - update handshake checksum + * - DTLS: save message for resending + * - then pass to the record layer + * + * DTLS: except for HelloRequest, messages are only queued, and will only be + * actually sent when calling flight_transmit() or resend(). + * + * Inputs: + * - ssl->out_msglen: 4 + actual handshake message len + * (4 is the size of handshake headers for TLS) + * - ssl->out_msg[0]: the handshake type (ClientHello, ServerHello, etc) + * - ssl->out_msg + 4: the handshake message body + * + * Outputs, ie state before passing to flight_append() or write_record(): + * - ssl->out_msglen: the length of the record contents + * (including handshake headers but excluding record headers) + * - ssl->out_msg: the record contents (handshake headers + content) */ -int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl ) +int mbedtls_ssl_write_handshake_msg( mbedtls_ssl_context *ssl ) { - int ret, done = 0, out_msg_type; - size_t len = ssl->out_msglen; + int ret; + const size_t hs_len = ssl->out_msglen - 4; + const unsigned char hs_type = ssl->out_msg[0]; - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write record" ) ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write handshake message" ) ); + + /* + * Sanity checks + */ + if( ssl->out_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE && + ssl->out_msgtype != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC ) + { + /* In SSLv3, the client might send a NoCertificate alert. */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) && defined(MBEDTLS_SSL_CLI_C) + if( ! ( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 && + ssl->out_msgtype == MBEDTLS_SSL_MSG_ALERT && + ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) ) +#endif /* MBEDTLS_SSL_PROTO_SSL3 && MBEDTLS_SSL_SRV_C */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + } + + /* Whenever we send anything different from a + * HelloRequest we should be in a handshake - double check. */ + if( ! ( ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && + hs_type == MBEDTLS_SSL_HS_HELLO_REQUEST ) && + ssl->handshake == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } #if defined(MBEDTLS_SSL_PROTO_DTLS) if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && ssl->handshake != NULL && ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING ) { - ; /* Skip special handshake treatment when resending */ + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); } - else #endif - if( ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) - { - out_msg_type = ssl->out_msg[0]; - if( out_msg_type != MBEDTLS_SSL_HS_HELLO_REQUEST && - ssl->handshake == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } + /* Double-check that we did not exceed the bounds + * of the outgoing record buffer. + * This should never fail as the various message + * writing functions must obey the bounds of the + * outgoing record buffer, but better be safe. + * + * Note: We deliberately do not check for the MTU or MFL here. + */ + if( ssl->out_msglen > MBEDTLS_SSL_OUT_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Record too large: " + "size %u, maximum %u", + (unsigned) ssl->out_msglen, + (unsigned) MBEDTLS_SSL_OUT_CONTENT_LEN ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } - ssl->out_msg[1] = (unsigned char)( ( len - 4 ) >> 16 ); - ssl->out_msg[2] = (unsigned char)( ( len - 4 ) >> 8 ); - ssl->out_msg[3] = (unsigned char)( ( len - 4 ) ); + /* + * Fill handshake headers + */ + if( ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) + { + ssl->out_msg[1] = (unsigned char)( hs_len >> 16 ); + ssl->out_msg[2] = (unsigned char)( hs_len >> 8 ); + ssl->out_msg[3] = (unsigned char)( hs_len ); /* * DTLS has additional fields in the Handshake layer, @@ -2980,17 +3262,16 @@ int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "DTLS handshake message too large: " "size %u, maximum %u", - (unsigned) ( ssl->in_hslen - 4 ), + (unsigned) ( hs_len ), (unsigned) ( MBEDTLS_SSL_OUT_CONTENT_LEN - 12 ) ) ); return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); } - memmove( ssl->out_msg + 12, ssl->out_msg + 4, len - 4 ); + memmove( ssl->out_msg + 12, ssl->out_msg + 4, hs_len ); ssl->out_msglen += 8; - len += 8; /* Write message_seq and update it, except for HelloRequest */ - if( out_msg_type != MBEDTLS_SSL_HS_HELLO_REQUEST ) + if( hs_type != MBEDTLS_SSL_HS_HELLO_REQUEST ) { ssl->out_msg[4] = ( ssl->handshake->out_msg_seq >> 8 ) & 0xFF; ssl->out_msg[5] = ( ssl->handshake->out_msg_seq ) & 0xFF; @@ -3002,23 +3283,23 @@ int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl ) ssl->out_msg[5] = 0; } - /* We don't fragment, so frag_offset = 0 and frag_len = len */ + /* Handshake hashes are computed without fragmentation, + * so set frag_offset = 0 and frag_len = hs_len for now */ memset( ssl->out_msg + 6, 0x00, 3 ); memcpy( ssl->out_msg + 9, ssl->out_msg + 1, 3 ); } #endif /* MBEDTLS_SSL_PROTO_DTLS */ - if( out_msg_type != MBEDTLS_SSL_HS_HELLO_REQUEST ) - ssl->handshake->update_checksum( ssl, ssl->out_msg, len ); + /* Update running hashes of handshake messages seen */ + if( hs_type != MBEDTLS_SSL_HS_HELLO_REQUEST ) + ssl->handshake->update_checksum( ssl, ssl->out_msg, ssl->out_msglen ); } - /* Save handshake and CCS messages for resending */ + /* Either send now, or just save to be sent (and resent) later */ #if defined(MBEDTLS_SSL_PROTO_DTLS) if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && - ssl->handshake != NULL && - ssl->handshake->retransmit_state != MBEDTLS_SSL_RETRANS_SENDING && - ( ssl->out_msgtype == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC || - ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) ) + ! ( ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && + hs_type == MBEDTLS_SSL_HS_HELLO_REQUEST ) ) { if( ( ret = ssl_flight_append( ssl ) ) != 0 ) { @@ -3026,7 +3307,40 @@ int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl ) return( ret ); } } + else #endif + { + if( ( ret = mbedtls_ssl_write_record( ssl, SSL_FORCE_FLUSH ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_record", ret ); + return( ret ); + } + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write handshake message" ) ); + + return( 0 ); +} + +/* + * Record layer functions + */ + +/* + * Write current record. + * + * Uses: + * - ssl->out_msgtype: type of the message (AppData, Handshake, Alert, CCS) + * - ssl->out_msglen: length of the record content (excl headers) + * - ssl->out_msg: record content + */ +int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl, uint8_t force_flush ) +{ + int ret, done = 0; + size_t len = ssl->out_msglen; + uint8_t flush = force_flush; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write record" ) ); #if defined(MBEDTLS_ZLIB_SUPPORT) if( ssl->transform_out != NULL && @@ -3060,10 +3374,14 @@ int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl ) #endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ if( !done ) { + unsigned i; + size_t protected_record_size; + ssl->out_hdr[0] = (unsigned char) ssl->out_msgtype; mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver, ssl->conf->transport, ssl->out_hdr + 1 ); + memcpy( ssl->out_ctr, ssl->cur_out_ctr, 8 ); ssl->out_len[0] = (unsigned char)( len >> 8 ); ssl->out_len[1] = (unsigned char)( len ); @@ -3080,18 +3398,76 @@ int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl ) ssl->out_len[1] = (unsigned char)( len ); } - ssl->out_left = mbedtls_ssl_hdr_len( ssl ) + ssl->out_msglen; + protected_record_size = len + mbedtls_ssl_hdr_len( ssl ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + /* In case of DTLS, double-check that we don't exceed + * the remaining space in the datagram. */ + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + ret = ssl_get_remaining_space_in_datagram( ssl ); + if( ret < 0 ) + return( ret ); + + if( protected_record_size > (size_t) ret ) + { + /* Should never happen */ + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ MBEDTLS_SSL_DEBUG_MSG( 3, ( "output record: msgtype = %d, " - "version = [%d:%d], msglen = %d", - ssl->out_hdr[0], ssl->out_hdr[1], ssl->out_hdr[2], - ( ssl->out_len[0] << 8 ) | ssl->out_len[1] ) ); + "version = [%d:%d], msglen = %d", + ssl->out_hdr[0], ssl->out_hdr[1], + ssl->out_hdr[2], len ) ); MBEDTLS_SSL_DEBUG_BUF( 4, "output record sent to network", - ssl->out_hdr, mbedtls_ssl_hdr_len( ssl ) + ssl->out_msglen ); + ssl->out_hdr, protected_record_size ); + + ssl->out_left += protected_record_size; + ssl->out_hdr += protected_record_size; + ssl_update_out_pointers( ssl, ssl->transform_out ); + + for( i = 8; i > ssl_ep_len( ssl ); i-- ) + if( ++ssl->cur_out_ctr[i - 1] != 0 ) + break; + + /* The loop goes to its end iff the counter is wrapping */ + if( i == ssl_ep_len( ssl ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "outgoing message counter would wrap" ) ); + return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING ); + } } - if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + flush == SSL_DONT_FORCE_FLUSH ) + { + size_t remaining; + ret = ssl_get_remaining_payload_in_datagram( ssl ); + if( ret < 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_get_remaining_payload_in_datagram", + ret ); + return( ret ); + } + + remaining = (size_t) ret; + if( remaining == 0 ) + { + flush = SSL_FORCE_FLUSH; + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Still %u bytes available in current datagram", (unsigned) remaining ) ); + } + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + if( ( flush == SSL_FORCE_FLUSH ) && + ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flush_output", ret ); return( ret ); @@ -3103,6 +3479,52 @@ int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl ) } #if defined(MBEDTLS_SSL_PROTO_DTLS) + +static int ssl_hs_is_proper_fragment( mbedtls_ssl_context *ssl ) +{ + if( ssl->in_msglen < ssl->in_hslen || + memcmp( ssl->in_msg + 6, "\0\0\0", 3 ) != 0 || + memcmp( ssl->in_msg + 9, ssl->in_msg + 1, 3 ) != 0 ) + { + return( 1 ); + } + return( 0 ); +} + +static uint32_t ssl_get_hs_frag_len( mbedtls_ssl_context const *ssl ) +{ + return( ( ssl->in_msg[9] << 16 ) | + ( ssl->in_msg[10] << 8 ) | + ssl->in_msg[11] ); +} + +static uint32_t ssl_get_hs_frag_off( mbedtls_ssl_context const *ssl ) +{ + return( ( ssl->in_msg[6] << 16 ) | + ( ssl->in_msg[7] << 8 ) | + ssl->in_msg[8] ); +} + +static int ssl_check_hs_header( mbedtls_ssl_context const *ssl ) +{ + uint32_t msg_len, frag_off, frag_len; + + msg_len = ssl_get_hs_total_len( ssl ); + frag_off = ssl_get_hs_frag_off( ssl ); + frag_len = ssl_get_hs_frag_len( ssl ); + + if( frag_off > msg_len ) + return( -1 ); + + if( frag_len > msg_len - frag_off ) + return( -1 ); + + if( frag_len + 12 > ssl->in_msglen ) + return( -1 ); + + return( 0 ); +} + /* * Mark bits in bitmask (used for DTLS HS reassembly) */ @@ -3164,161 +3586,29 @@ static int ssl_bitmask_check( unsigned char *mask, size_t len ) return( 0 ); } -/* - * Reassemble fragmented DTLS handshake messages. - * - * Use a temporary buffer for reassembly, divided in two parts: - * - the first holds the reassembled message (including handshake header), - * - the second holds a bitmask indicating which parts of the message - * (excluding headers) have been received so far. - */ -static int ssl_reassemble_dtls_handshake( mbedtls_ssl_context *ssl ) +/* msg_len does not include the handshake header */ +static size_t ssl_get_reassembly_buffer_size( size_t msg_len, + unsigned add_bitmap ) { - unsigned char *msg, *bitmask; - size_t frag_len, frag_off; - size_t msg_len = ssl->in_hslen - 12; /* Without headers */ - - if( ssl->handshake == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "not supported outside handshake (for now)" ) ); - return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); - } - - /* - * For first fragment, check size and allocate buffer - */ - if( ssl->handshake->hs_msg == NULL ) - { - size_t alloc_len; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialize reassembly, total length = %d", - msg_len ) ); - - if( ssl->in_hslen > MBEDTLS_SSL_IN_CONTENT_LEN ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake message too large" ) ); - return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); - } - - /* The bitmask needs one bit per byte of message excluding header */ - alloc_len = 12 + msg_len + msg_len / 8 + ( msg_len % 8 != 0 ); - - ssl->handshake->hs_msg = mbedtls_calloc( 1, alloc_len ); - if( ssl->handshake->hs_msg == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc failed (%d bytes)", alloc_len ) ); - return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); - } - - /* Prepare final header: copy msg_type, length and message_seq, - * then add standardised fragment_offset and fragment_length */ - memcpy( ssl->handshake->hs_msg, ssl->in_msg, 6 ); - memset( ssl->handshake->hs_msg + 6, 0, 3 ); - memcpy( ssl->handshake->hs_msg + 9, - ssl->handshake->hs_msg + 1, 3 ); - } - else - { - /* Make sure msg_type and length are consistent */ - if( memcmp( ssl->handshake->hs_msg, ssl->in_msg, 4 ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "fragment header mismatch" ) ); - return( MBEDTLS_ERR_SSL_INVALID_RECORD ); - } - } - - msg = ssl->handshake->hs_msg + 12; - bitmask = msg + msg_len; - - /* - * Check and copy current fragment - */ - frag_off = ( ssl->in_msg[6] << 16 ) | - ( ssl->in_msg[7] << 8 ) | - ssl->in_msg[8]; - frag_len = ( ssl->in_msg[9] << 16 ) | - ( ssl->in_msg[10] << 8 ) | - ssl->in_msg[11]; - - if( frag_off + frag_len > msg_len ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid fragment offset/len: %d + %d > %d", - frag_off, frag_len, msg_len ) ); - return( MBEDTLS_ERR_SSL_INVALID_RECORD ); - } - - if( frag_len + 12 > ssl->in_msglen ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid fragment length: %d + 12 > %d", - frag_len, ssl->in_msglen ) ); - return( MBEDTLS_ERR_SSL_INVALID_RECORD ); - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "adding fragment, offset = %d, length = %d", - frag_off, frag_len ) ); - - memcpy( msg + frag_off, ssl->in_msg + 12, frag_len ); - ssl_bitmask_set( bitmask, frag_off, frag_len ); - - /* - * Do we have the complete message by now? - * If yes, finalize it, else ask to read the next record. - */ - if( ssl_bitmask_check( bitmask, msg_len ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "message is not complete yet" ) ); - return( MBEDTLS_ERR_SSL_CONTINUE_PROCESSING ); - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "handshake message completed" ) ); - - if( frag_len + 12 < ssl->in_msglen ) - { - /* - * We'got more handshake messages in the same record. - * This case is not handled now because no know implementation does - * that and it's hard to test, so we prefer to fail cleanly for now. - */ - MBEDTLS_SSL_DEBUG_MSG( 1, ( "last fragment not alone in its record" ) ); - return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); - } - - if( ssl->in_left > ssl->next_record_offset ) - { - /* - * We've got more data in the buffer after the current record, - * that we don't want to overwrite. Move it before writing the - * reassembled message, and adjust in_left and next_record_offset. - */ - unsigned char *cur_remain = ssl->in_hdr + ssl->next_record_offset; - unsigned char *new_remain = ssl->in_msg + ssl->in_hslen; - size_t remain_len = ssl->in_left - ssl->next_record_offset; - - /* First compute and check new lengths */ - ssl->next_record_offset = new_remain - ssl->in_hdr; - ssl->in_left = ssl->next_record_offset + remain_len; - - if( ssl->in_left > MBEDTLS_SSL_IN_BUFFER_LEN - - (size_t)( ssl->in_hdr - ssl->in_buf ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "reassembled message too large for buffer" ) ); - return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); - } + size_t alloc_len; - memmove( new_remain, cur_remain, remain_len ); - } + alloc_len = 12; /* Handshake header */ + alloc_len += msg_len; /* Content buffer */ - memcpy( ssl->in_msg, ssl->handshake->hs_msg, ssl->in_hslen ); + if( add_bitmap ) + alloc_len += msg_len / 8 + ( msg_len % 8 != 0 ); /* Bitmap */ - mbedtls_free( ssl->handshake->hs_msg ); - ssl->handshake->hs_msg = NULL; + return( alloc_len ); +} - MBEDTLS_SSL_DEBUG_BUF( 3, "reassembled handshake message", - ssl->in_msg, ssl->in_hslen ); +#endif /* MBEDTLS_SSL_PROTO_DTLS */ - return( 0 ); +static uint32_t ssl_get_hs_total_len( mbedtls_ssl_context const *ssl ) +{ + return( ( ssl->in_msg[1] << 16 ) | + ( ssl->in_msg[2] << 8 ) | + ssl->in_msg[3] ); } -#endif /* MBEDTLS_SSL_PROTO_DTLS */ int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl ) { @@ -3329,10 +3619,7 @@ int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl ) return( MBEDTLS_ERR_SSL_INVALID_RECORD ); } - ssl->in_hslen = mbedtls_ssl_hs_hdr_len( ssl ) + ( - ( ssl->in_msg[1] << 16 ) | - ( ssl->in_msg[2] << 8 ) | - ssl->in_msg[3] ); + ssl->in_hslen = mbedtls_ssl_hs_hdr_len( ssl ) + ssl_get_hs_total_len( ssl ); MBEDTLS_SSL_DEBUG_MSG( 3, ( "handshake message: msglen =" " %d, type = %d, hslen = %d", @@ -3344,12 +3631,26 @@ int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl ) int ret; unsigned int recv_msg_seq = ( ssl->in_msg[4] << 8 ) | ssl->in_msg[5]; + if( ssl_check_hs_header( ssl ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid handshake header" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + if( ssl->handshake != NULL && ( ( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER && recv_msg_seq != ssl->handshake->in_msg_seq ) || ( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER && ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_HELLO ) ) ) { + if( recv_msg_seq > ssl->handshake->in_msg_seq ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "received future handshake message of sequence number %u (next %u)", + recv_msg_seq, + ssl->handshake->in_msg_seq ) ); + return( MBEDTLS_ERR_SSL_EARLY_MESSAGE ); + } + /* Retransmit only on last message from previous flight, to avoid * too many retransmissions. * Besides, No sane server ever retransmits HelloVerifyRequest */ @@ -3379,20 +3680,14 @@ int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl ) } /* Wait until message completion to increment in_msg_seq */ - /* Reassemble if current message is fragmented or reassembly is - * already in progress */ - if( ssl->in_msglen < ssl->in_hslen || - memcmp( ssl->in_msg + 6, "\0\0\0", 3 ) != 0 || - memcmp( ssl->in_msg + 9, ssl->in_msg + 1, 3 ) != 0 || - ( ssl->handshake != NULL && ssl->handshake->hs_msg != NULL ) ) + /* Message reassembly is handled alongside buffering of future + * messages; the commonality is that both handshake fragments and + * future messages cannot be forwarded immediately to the + * handshake logic layer. */ + if( ssl_hs_is_proper_fragment( ssl ) == 1 ) { MBEDTLS_SSL_DEBUG_MSG( 2, ( "found fragmented DTLS handshake message" ) ); - - if( ( ret = ssl_reassemble_dtls_handshake( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "ssl_reassemble_dtls_handshake", ret ); - return( ret ); - } + return( MBEDTLS_ERR_SSL_EARLY_MESSAGE ); } } else @@ -3409,9 +3704,9 @@ int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl ) void mbedtls_ssl_update_handshake_status( mbedtls_ssl_context *ssl ) { + mbedtls_ssl_handshake_params * const hs = ssl->handshake; - if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER && - ssl->handshake != NULL ) + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER && hs != NULL ) { ssl->handshake->update_checksum( ssl, ssl->in_msg, ssl->in_hslen ); } @@ -3421,7 +3716,29 @@ void mbedtls_ssl_update_handshake_status( mbedtls_ssl_context *ssl ) if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && ssl->handshake != NULL ) { - ssl->handshake->in_msg_seq++; + unsigned offset; + mbedtls_ssl_hs_buffer *hs_buf; + + /* Increment handshake sequence number */ + hs->in_msg_seq++; + + /* + * Clear up handshake buffering and reassembly structure. + */ + + /* Free first entry */ + ssl_buffering_free_slot( ssl, 0 ); + + /* Shift all other entries */ + for( offset = 0, hs_buf = &hs->buffering.hs[0]; + offset + 1 < MBEDTLS_SSL_MAX_BUFFERED_HS; + offset++, hs_buf++ ) + { + *hs_buf = *(hs_buf + 1); + } + + /* Create a fresh last entry */ + memset( hs_buf, 0, sizeof( mbedtls_ssl_hs_buffer ) ); } #endif } @@ -3822,7 +4139,16 @@ static int ssl_parse_record_header( mbedtls_ssl_context *ssl ) } else #endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */ + { + /* Consider buffering the record. */ + if( rec_epoch == (unsigned int) ssl->in_epoch + 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Consider record for buffering" ) ); + return( MBEDTLS_ERR_SSL_EARLY_MESSAGE ); + } + return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ); + } } #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) @@ -3835,15 +4161,6 @@ static int ssl_parse_record_header( mbedtls_ssl_context *ssl ) } #endif - /* Drop unexpected ChangeCipherSpec messages */ - if( ssl->in_msgtype == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC && - ssl->state != MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC && - ssl->state != MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "dropping unexpected ChangeCipherSpec" ) ); - return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ); - } - /* Drop unexpected ApplicationData records, * except at the beginning of renegotiations */ if( ssl->in_msgtype == MBEDTLS_SSL_MSG_APPLICATION_DATA && @@ -3980,7 +4297,14 @@ static void ssl_handshake_wrapup_free_hs_transform( mbedtls_ssl_context *ssl ); * RFC 6347 4.1.2.7) and continue reading until a valid record is found. * */ -int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl ) + +/* Helper functions for mbedtls_ssl_read_record(). */ +static int ssl_consume_current_message( mbedtls_ssl_context *ssl ); +static int ssl_get_next_record( mbedtls_ssl_context *ssl ); +static int ssl_record_is_in_progress( mbedtls_ssl_context *ssl ); + +int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl, + unsigned update_hs_digest ) { int ret; @@ -3990,17 +4314,53 @@ int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl ) { do { - do ret = mbedtls_ssl_read_record_layer( ssl ); - while( ret == MBEDTLS_ERR_SSL_CONTINUE_PROCESSING ); - + ret = ssl_consume_current_message( ssl ); if( ret != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_read_record_layer" ), ret ); return( ret ); + + if( ssl_record_is_in_progress( ssl ) == 0 ) + { +#if defined(MBEDTLS_SSL_PROTO_DTLS) + int have_buffered = 0; + + /* We only check for buffered messages if the + * current datagram is fully consumed. */ + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl_next_record_is_in_datagram( ssl ) == 0 ) + { + if( ssl_load_buffered_message( ssl ) == 0 ) + have_buffered = 1; + } + + if( have_buffered == 0 ) +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + { + ret = ssl_get_next_record( ssl ); + if( ret == MBEDTLS_ERR_SSL_CONTINUE_PROCESSING ) + continue; + + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_get_next_record" ), ret ); + return( ret ); + } + } } ret = mbedtls_ssl_handle_message_type( ssl ); +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ret == MBEDTLS_ERR_SSL_EARLY_MESSAGE ) + { + /* Buffer future message */ + ret = ssl_buffer_message( ssl ); + if( ret != 0 ) + return( ret ); + + ret = MBEDTLS_ERR_SSL_CONTINUE_PROCESSING; + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + } while( MBEDTLS_ERR_SSL_NON_FATAL == ret || MBEDTLS_ERR_SSL_CONTINUE_PROCESSING == ret ); @@ -4010,14 +4370,15 @@ int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl ) return( ret ); } - if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && + update_hs_digest == 1 ) { mbedtls_ssl_update_handshake_status( ssl ); } } else { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= reuse previously read message" ) ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "reuse previously read message" ) ); ssl->keep_current_message = 0; } @@ -4026,13 +4387,350 @@ int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl ) return( 0 ); } -int mbedtls_ssl_read_record_layer( mbedtls_ssl_context *ssl ) +#if defined(MBEDTLS_SSL_PROTO_DTLS) +static int ssl_next_record_is_in_datagram( mbedtls_ssl_context *ssl ) { - int ret; + if( ssl->in_left > ssl->next_record_offset ) + return( 1 ); + + return( 0 ); +} + +static int ssl_load_buffered_message( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_handshake_params * const hs = ssl->handshake; + mbedtls_ssl_hs_buffer * hs_buf; + int ret = 0; + + if( hs == NULL ) + return( -1 ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_load_buffered_messsage" ) ); + + if( ssl->state == MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC || + ssl->state == MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC ) + { + /* Check if we have seen a ChangeCipherSpec before. + * If yes, synthesize a CCS record. */ + if( !hs->buffering.seen_ccs ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "CCS not seen in the current flight" ) ); + ret = -1; + goto exit; + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Injecting buffered CCS message" ) ); + ssl->in_msgtype = MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC; + ssl->in_msglen = 1; + ssl->in_msg[0] = 1; + + /* As long as they are equal, the exact value doesn't matter. */ + ssl->in_left = 0; + ssl->next_record_offset = 0; + + hs->buffering.seen_ccs = 0; + goto exit; + } + +#if defined(MBEDTLS_DEBUG_C) + /* Debug only */ + { + unsigned offset; + for( offset = 1; offset < MBEDTLS_SSL_MAX_BUFFERED_HS; offset++ ) + { + hs_buf = &hs->buffering.hs[offset]; + if( hs_buf->is_valid == 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Future message with sequence number %u %s buffered.", + hs->in_msg_seq + offset, + hs_buf->is_complete ? "fully" : "partially" ) ); + } + } + } +#endif /* MBEDTLS_DEBUG_C */ + + /* Check if we have buffered and/or fully reassembled the + * next handshake message. */ + hs_buf = &hs->buffering.hs[0]; + if( ( hs_buf->is_valid == 1 ) && ( hs_buf->is_complete == 1 ) ) + { + /* Synthesize a record containing the buffered HS message. */ + size_t msg_len = ( hs_buf->data[1] << 16 ) | + ( hs_buf->data[2] << 8 ) | + hs_buf->data[3]; + + /* Double-check that we haven't accidentally buffered + * a message that doesn't fit into the input buffer. */ + if( msg_len + 12 > MBEDTLS_SSL_IN_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Next handshake message has been buffered - load" ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "Buffered handshake message (incl. header)", + hs_buf->data, msg_len + 12 ); + + ssl->in_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->in_hslen = msg_len + 12; + ssl->in_msglen = msg_len + 12; + memcpy( ssl->in_msg, hs_buf->data, ssl->in_hslen ); + + ret = 0; + goto exit; + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Next handshake message %u not or only partially bufffered", + hs->in_msg_seq ) ); + } + + ret = -1; + +exit: + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_load_buffered_message" ) ); + return( ret ); +} + +static int ssl_buffer_make_space( mbedtls_ssl_context *ssl, + size_t desired ) +{ + int offset; + mbedtls_ssl_handshake_params * const hs = ssl->handshake; + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Attempt to free buffered messages to have %u bytes available", + (unsigned) desired ) ); + + /* Get rid of future records epoch first, if such exist. */ + ssl_free_buffered_record( ssl ); + + /* Check if we have enough space available now. */ + if( desired <= ( MBEDTLS_SSL_DTLS_MAX_BUFFERING - + hs->buffering.total_bytes_buffered ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Enough space available after freeing future epoch record" ) ); + return( 0 ); + } + + /* We don't have enough space to buffer the next expected handshake + * message. Remove buffers used for future messages to gain space, + * starting with the most distant one. */ + for( offset = MBEDTLS_SSL_MAX_BUFFERED_HS - 1; + offset >= 0; offset-- ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Free buffering slot %d to make space for reassembly of next handshake message", + offset ) ); + + ssl_buffering_free_slot( ssl, (uint8_t) offset ); + + /* Check if we have enough space available now. */ + if( desired <= ( MBEDTLS_SSL_DTLS_MAX_BUFFERING - + hs->buffering.total_bytes_buffered ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Enough space available after freeing buffered HS messages" ) ); + return( 0 ); + } + } + + return( -1 ); +} + +static int ssl_buffer_message( mbedtls_ssl_context *ssl ) +{ + int ret = 0; + mbedtls_ssl_handshake_params * const hs = ssl->handshake; + + if( hs == NULL ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_buffer_message" ) ); + + switch( ssl->in_msgtype ) + { + case MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC: + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Remember CCS message" ) ); + + hs->buffering.seen_ccs = 1; + break; + + case MBEDTLS_SSL_MSG_HANDSHAKE: + { + unsigned recv_msg_seq_offset; + unsigned recv_msg_seq = ( ssl->in_msg[4] << 8 ) | ssl->in_msg[5]; + mbedtls_ssl_hs_buffer *hs_buf; + size_t msg_len = ssl->in_hslen - 12; + + /* We should never receive an old handshake + * message - double-check nonetheless. */ + if( recv_msg_seq < ssl->handshake->in_msg_seq ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + recv_msg_seq_offset = recv_msg_seq - ssl->handshake->in_msg_seq; + if( recv_msg_seq_offset >= MBEDTLS_SSL_MAX_BUFFERED_HS ) + { + /* Silently ignore -- message too far in the future */ + MBEDTLS_SSL_DEBUG_MSG( 2, + ( "Ignore future HS message with sequence number %u, " + "buffering window %u - %u", + recv_msg_seq, ssl->handshake->in_msg_seq, + ssl->handshake->in_msg_seq + MBEDTLS_SSL_MAX_BUFFERED_HS - 1 ) ); + + goto exit; + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering HS message with sequence number %u, offset %u ", + recv_msg_seq, recv_msg_seq_offset ) ); + + hs_buf = &hs->buffering.hs[ recv_msg_seq_offset ]; + + /* Check if the buffering for this seq nr has already commenced. */ + if( !hs_buf->is_valid ) + { + size_t reassembly_buf_sz; + + hs_buf->is_fragmented = + ( ssl_hs_is_proper_fragment( ssl ) == 1 ); + + /* We copy the message back into the input buffer + * after reassembly, so check that it's not too large. + * This is an implementation-specific limitation + * and not one from the standard, hence it is not + * checked in ssl_check_hs_header(). */ + if( msg_len + 12 > MBEDTLS_SSL_IN_CONTENT_LEN ) + { + /* Ignore message */ + goto exit; + } + /* Check if we have enough space to buffer the message. */ + if( hs->buffering.total_bytes_buffered > + MBEDTLS_SSL_DTLS_MAX_BUFFERING ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + reassembly_buf_sz = ssl_get_reassembly_buffer_size( msg_len, + hs_buf->is_fragmented ); + + if( reassembly_buf_sz > ( MBEDTLS_SSL_DTLS_MAX_BUFFERING - + hs->buffering.total_bytes_buffered ) ) + { + if( recv_msg_seq_offset > 0 ) + { + /* If we can't buffer a future message because + * of space limitations -- ignore. */ + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering of future message of size %u would exceed the compile-time limit %u (already %u bytes buffered) -- ignore\n", + (unsigned) msg_len, MBEDTLS_SSL_DTLS_MAX_BUFFERING, + (unsigned) hs->buffering.total_bytes_buffered ) ); + goto exit; + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering of future message of size %u would exceed the compile-time limit %u (already %u bytes buffered) -- attempt to make space by freeing buffered future messages\n", + (unsigned) msg_len, MBEDTLS_SSL_DTLS_MAX_BUFFERING, + (unsigned) hs->buffering.total_bytes_buffered ) ); + } + + if( ssl_buffer_make_space( ssl, reassembly_buf_sz ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Reassembly of next message of size %u (%u with bitmap) would exceed the compile-time limit %u (already %u bytes buffered) -- fail\n", + (unsigned) msg_len, + (unsigned) reassembly_buf_sz, + MBEDTLS_SSL_DTLS_MAX_BUFFERING, + (unsigned) hs->buffering.total_bytes_buffered ) ); + ret = MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; + goto exit; + } + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialize reassembly, total length = %d", + msg_len ) ); + + hs_buf->data = mbedtls_calloc( 1, reassembly_buf_sz ); + if( hs_buf->data == NULL ) + { + ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; + goto exit; + } + hs_buf->data_len = reassembly_buf_sz; + + /* Prepare final header: copy msg_type, length and message_seq, + * then add standardised fragment_offset and fragment_length */ + memcpy( hs_buf->data, ssl->in_msg, 6 ); + memset( hs_buf->data + 6, 0, 3 ); + memcpy( hs_buf->data + 9, hs_buf->data + 1, 3 ); + + hs_buf->is_valid = 1; + + hs->buffering.total_bytes_buffered += reassembly_buf_sz; + } + else + { + /* Make sure msg_type and length are consistent */ + if( memcmp( hs_buf->data, ssl->in_msg, 4 ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Fragment header mismatch - ignore" ) ); + /* Ignore */ + goto exit; + } + } + + if( !hs_buf->is_complete ) + { + size_t frag_len, frag_off; + unsigned char * const msg = hs_buf->data + 12; + + /* + * Check and copy current fragment + */ + + /* Validation of header fields already done in + * mbedtls_ssl_prepare_handshake_record(). */ + frag_off = ssl_get_hs_frag_off( ssl ); + frag_len = ssl_get_hs_frag_len( ssl ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "adding fragment, offset = %d, length = %d", + frag_off, frag_len ) ); + memcpy( msg + frag_off, ssl->in_msg + 12, frag_len ); + + if( hs_buf->is_fragmented ) + { + unsigned char * const bitmask = msg + msg_len; + ssl_bitmask_set( bitmask, frag_off, frag_len ); + hs_buf->is_complete = ( ssl_bitmask_check( bitmask, + msg_len ) == 0 ); + } + else + { + hs_buf->is_complete = 1; + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "message %scomplete", + hs_buf->is_complete ? "" : "not yet " ) ); + } + + break; + } + + default: + /* We don't buffer other types of messages. */ + break; + } + +exit: + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_buffer_message" ) ); + return( ret ); +} +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +static int ssl_consume_current_message( mbedtls_ssl_context *ssl ) +{ /* - * Step A - * * Consume last content-layer message and potentially * update in_msglen which keeps track of the contents' * consumption state. @@ -4114,20 +4812,161 @@ int mbedtls_ssl_read_record_layer( mbedtls_ssl_context *ssl ) ssl->in_msglen = 0; } - /* - * Step B - * - * Fetch and decode new record if current one is fully consumed. - * - */ + return( 0 ); +} +static int ssl_record_is_in_progress( mbedtls_ssl_context *ssl ) +{ if( ssl->in_msglen > 0 ) + return( 1 ); + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + +static void ssl_free_buffered_record( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_handshake_params * const hs = ssl->handshake; + if( hs == NULL ) + return; + + if( hs->buffering.future_record.data != NULL ) { - /* There's something left to be processed in the current record. */ + hs->buffering.total_bytes_buffered -= + hs->buffering.future_record.len; + + mbedtls_free( hs->buffering.future_record.data ); + hs->buffering.future_record.data = NULL; + } +} + +static int ssl_load_buffered_record( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_handshake_params * const hs = ssl->handshake; + unsigned char * rec; + size_t rec_len; + unsigned rec_epoch; + + if( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + return( 0 ); + + if( hs == NULL ) + return( 0 ); + + rec = hs->buffering.future_record.data; + rec_len = hs->buffering.future_record.len; + rec_epoch = hs->buffering.future_record.epoch; + + if( rec == NULL ) return( 0 ); + + /* Only consider loading future records if the + * input buffer is empty. */ + if( ssl_next_record_is_in_datagram( ssl ) == 1 ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_load_buffered_record" ) ); + + if( rec_epoch != ssl->in_epoch ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffered record not from current epoch." ) ); + goto exit; } - /* Current record either fully processed or to be discarded. */ + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Found buffered record from current epoch - load" ) ); + + /* Double-check that the record is not too large */ + if( rec_len > MBEDTLS_SSL_IN_BUFFER_LEN - + (size_t)( ssl->in_hdr - ssl->in_buf ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + memcpy( ssl->in_hdr, rec, rec_len ); + ssl->in_left = rec_len; + ssl->next_record_offset = 0; + + ssl_free_buffered_record( ssl ); + +exit: + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_load_buffered_record" ) ); + return( 0 ); +} + +static int ssl_buffer_future_record( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_handshake_params * const hs = ssl->handshake; + size_t const rec_hdr_len = 13; + size_t const total_buf_sz = rec_hdr_len + ssl->in_msglen; + + /* Don't buffer future records outside handshakes. */ + if( hs == NULL ) + return( 0 ); + + /* Only buffer handshake records (we are only interested + * in Finished messages). */ + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) + return( 0 ); + + /* Don't buffer more than one future epoch record. */ + if( hs->buffering.future_record.data != NULL ) + return( 0 ); + + /* Don't buffer record if there's not enough buffering space remaining. */ + if( total_buf_sz > ( MBEDTLS_SSL_DTLS_MAX_BUFFERING - + hs->buffering.total_bytes_buffered ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering of future epoch record of size %u would exceed the compile-time limit %u (already %u bytes buffered) -- ignore\n", + (unsigned) total_buf_sz, MBEDTLS_SSL_DTLS_MAX_BUFFERING, + (unsigned) hs->buffering.total_bytes_buffered ) ); + return( 0 ); + } + + /* Buffer record */ + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffer record from epoch %u", + ssl->in_epoch + 1 ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "Buffered record", ssl->in_hdr, + rec_hdr_len + ssl->in_msglen ); + + /* ssl_parse_record_header() only considers records + * of the next epoch as candidates for buffering. */ + hs->buffering.future_record.epoch = ssl->in_epoch + 1; + hs->buffering.future_record.len = total_buf_sz; + + hs->buffering.future_record.data = + mbedtls_calloc( 1, hs->buffering.future_record.len ); + if( hs->buffering.future_record.data == NULL ) + { + /* If we run out of RAM trying to buffer a + * record from the next epoch, just ignore. */ + return( 0 ); + } + + memcpy( hs->buffering.future_record.data, ssl->in_hdr, total_buf_sz ); + + hs->buffering.total_bytes_buffered += total_buf_sz; + return( 0 ); +} + +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +static int ssl_get_next_record( mbedtls_ssl_context *ssl ) +{ + int ret; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + /* We might have buffered a future record; if so, + * and if the epoch matches now, load it. + * On success, this call will set ssl->in_left to + * the length of the buffered record, so that + * the calls to ssl_fetch_input() below will + * essentially be no-ops. */ + ret = ssl_load_buffered_record( ssl ); + if( ret != 0 ) + return( ret ); +#endif /* MBEDTLS_SSL_PROTO_DTLS */ if( ( ret = mbedtls_ssl_fetch_input( ssl, mbedtls_ssl_hdr_len( ssl ) ) ) != 0 ) { @@ -4141,6 +4980,16 @@ int mbedtls_ssl_read_record_layer( mbedtls_ssl_context *ssl ) if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && ret != MBEDTLS_ERR_SSL_CLIENT_RECONNECT ) { + if( ret == MBEDTLS_ERR_SSL_EARLY_MESSAGE ) + { + ret = ssl_buffer_future_record( ssl ); + if( ret != 0 ) + return( ret ); + + /* Fall through to handling of unexpected records */ + ret = MBEDTLS_ERR_SSL_UNEXPECTED_RECORD; + } + if( ret == MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ) { /* Skip unexpected record (but not whole datagram) */ @@ -4272,6 +5121,39 @@ int mbedtls_ssl_handle_message_type( mbedtls_ssl_context *ssl ) } } + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC ) + { + if( ssl->in_msglen != 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid CCS message, len: %d", + ssl->in_msglen ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + if( ssl->in_msg[0] != 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid CCS message, content: %02x", + ssl->in_msg[0] ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->state != MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC && + ssl->state != MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC ) + { + if( ssl->handshake == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "dropping ChangeCipherSpec outside handshake" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ); + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "received out-of-order ChangeCipherSpec - remember" ) ); + return( MBEDTLS_ERR_SSL_EARLY_MESSAGE ); + } +#endif + } + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT ) { if( ssl->in_msglen != 2 ) @@ -4373,7 +5255,7 @@ int mbedtls_ssl_send_alert_message( mbedtls_ssl_context *ssl, ssl->out_msg[0] = level; ssl->out_msg[1] = message; - if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + if( ( ret = mbedtls_ssl_write_record( ssl, SSL_FORCE_FLUSH ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); return( ret ); @@ -4542,9 +5424,9 @@ write_msg: ssl->state++; - if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); return( ret ); } @@ -4553,60 +5435,16 @@ write_msg: return( ret ); } -int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) +/* + * Once the certificate message is read, parse it into a cert chain and + * perform basic checks, but leave actual verification to the caller + */ +static int ssl_parse_certificate_chain( mbedtls_ssl_context *ssl ) { - int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + int ret; size_t i, n; - const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; - int authmode = ssl->conf->authmode; uint8_t alert; - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) ); - - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) ); - ssl->state++; - return( 0 ); - } - -#if defined(MBEDTLS_SSL_SRV_C) - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) ); - ssl->state++; - return( 0 ); - } - -#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) - if( ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET ) - authmode = ssl->handshake->sni_authmode; -#endif - - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && - authmode == MBEDTLS_SSL_VERIFY_NONE ) - { - ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_SKIP_VERIFY; - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) ); - ssl->state++; - return( 0 ); - } -#endif - - if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) - { - /* mbedtls_ssl_read_record may have sent an alert already. We - let it decide whether to alert. */ - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); - return( ret ); - } - - ssl->state++; - #if defined(MBEDTLS_SSL_SRV_C) #if defined(MBEDTLS_SSL_PROTO_SSL3) /* @@ -4626,10 +5464,7 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) one. The client should know what's going on, so we don't send an alert. */ ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING; - if( authmode == MBEDTLS_SSL_VERIFY_OPTIONAL ) - return( 0 ); - else - return( MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE ); + return( MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE ); } } #endif /* MBEDTLS_SSL_PROTO_SSL3 */ @@ -4650,10 +5485,7 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) one. The client should know what's going on, so we don't send an alert. */ ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING; - if( authmode == MBEDTLS_SSL_VERIFY_OPTIONAL ) - return( 0 ); - else - return( MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE ); + return( MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE ); } } #endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ @@ -4803,6 +5635,94 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) } #endif /* MBEDTLS_SSL_RENEGOTIATION && MBEDTLS_SSL_CLI_C */ + return( 0 ); +} + +int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) +{ + int ret; + const mbedtls_ssl_ciphersuite_t * const ciphersuite_info = + ssl->transform_negotiate->ciphersuite_info; +#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + const int authmode = ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET + ? ssl->handshake->sni_authmode + : ssl->conf->authmode; +#else + const int authmode = ssl->conf->authmode; +#endif + void *rs_ctx = NULL; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) ); + + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) ); + ssl->state++; + return( 0 ); + } + +#if defined(MBEDTLS_SSL_SRV_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) ); + ssl->state++; + return( 0 ); + } + + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && + authmode == MBEDTLS_SSL_VERIFY_NONE ) + { + ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_SKIP_VERIFY; + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) ); + + ssl->state++; + return( 0 ); + } +#endif + +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ssl->handshake->ecrs_enabled && + ssl->handshake->ecrs_state == ssl_ecrs_crt_verify ) + { + goto crt_verify; + } +#endif + + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) + { + /* mbedtls_ssl_read_record may have sent an alert already. We + let it decide whether to alert. */ + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + if( ( ret = ssl_parse_certificate_chain( ssl ) ) != 0 ) + { +#if defined(MBEDTLS_SSL_SRV_C) + if( ret == MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE && + authmode == MBEDTLS_SSL_VERIFY_OPTIONAL ) + { + ret = 0; + } +#endif + + ssl->state++; + return( ret ); + } + +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ssl->handshake->ecrs_enabled) + ssl->handshake->ecrs_state = ssl_ecrs_crt_verify; + +crt_verify: + if( ssl->handshake->ecrs_enabled) + rs_ctx = &ssl->handshake->ecrs_ctx; +#endif + if( authmode != MBEDTLS_SSL_VERIFY_NONE ) { mbedtls_x509_crt *ca_chain; @@ -4824,19 +5744,24 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) /* * Main check: verify certificate */ - ret = mbedtls_x509_crt_verify_with_profile( + ret = mbedtls_x509_crt_verify_restartable( ssl->session_negotiate->peer_cert, ca_chain, ca_crl, ssl->conf->cert_profile, ssl->hostname, &ssl->session_negotiate->verify_result, - ssl->conf->f_vrfy, ssl->conf->p_vrfy ); + ssl->conf->f_vrfy, ssl->conf->p_vrfy, rs_ctx ); if( ret != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "x509_verify_cert", ret ); } +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + return( MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS ); +#endif + /* * Secondary checks: always done, but change 'ret' only if it was 0 */ @@ -4889,6 +5814,8 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) if( ret != 0 ) { + uint8_t alert; + /* The certificate may have been rejected for several reasons. Pick one and send the corresponding alert. Which alert to send may be a subject of debate in some cases. */ @@ -4931,6 +5858,8 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) #endif /* MBEDTLS_DEBUG_C */ } + ssl->state++; + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse certificate" ) ); return( ret ); @@ -4955,9 +5884,9 @@ int mbedtls_ssl_write_change_cipher_spec( mbedtls_ssl_context *ssl ) ssl->state++; - if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); return( ret ); } @@ -4972,7 +5901,7 @@ int mbedtls_ssl_parse_change_cipher_spec( mbedtls_ssl_context *ssl ) MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse change cipher spec" ) ); - if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); return( ret ); @@ -4986,13 +5915,8 @@ int mbedtls_ssl_parse_change_cipher_spec( mbedtls_ssl_context *ssl ) return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); } - if( ssl->in_msglen != 1 || ssl->in_msg[0] != 1 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad change cipher spec message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); - return( MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC ); - } + /* CCS records are only accepted if they have length 1 and content '1', + * so we don't need to check this here. */ /* * Switch to our negotiated transform and session parameters for inbound @@ -5022,16 +5946,7 @@ int mbedtls_ssl_parse_change_cipher_spec( mbedtls_ssl_context *ssl ) #endif /* MBEDTLS_SSL_PROTO_DTLS */ memset( ssl->in_ctr, 0, 8 ); - /* - * Set the in_msg pointer to the correct location based on IV length - */ - if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) - { - ssl->in_msg = ssl->in_iv + ssl->transform_negotiate->ivlen - - ssl->transform_negotiate->fixed_ivlen; - } - else - ssl->in_msg = ssl->in_iv; + ssl_update_in_pointers( ssl, ssl->transform_negotiate ); #if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) if( mbedtls_ssl_hw_record_activate != NULL ) @@ -5482,16 +6397,7 @@ int mbedtls_ssl_write_finished( mbedtls_ssl_context *ssl ) MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write finished" ) ); - /* - * Set the out_msg pointer to the correct location based on IV length - */ - if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) - { - ssl->out_msg = ssl->out_iv + ssl->transform_negotiate->ivlen - - ssl->transform_negotiate->fixed_ivlen; - } - else - ssl->out_msg = ssl->out_iv; + ssl_update_out_pointers( ssl, ssl->transform_negotiate ); ssl->handshake->calc_finished( ssl, ssl->out_msg + 4, ssl->conf->endpoint ); @@ -5543,14 +6449,14 @@ int mbedtls_ssl_write_finished( mbedtls_ssl_context *ssl ) /* Remember current epoch settings for resending */ ssl->handshake->alt_transform_out = ssl->transform_out; - memcpy( ssl->handshake->alt_out_ctr, ssl->out_ctr, 8 ); + memcpy( ssl->handshake->alt_out_ctr, ssl->cur_out_ctr, 8 ); /* Set sequence_number to zero */ - memset( ssl->out_ctr + 2, 0, 6 ); + memset( ssl->cur_out_ctr + 2, 0, 6 ); /* Increment epoch */ for( i = 2; i > 0; i-- ) - if( ++ssl->out_ctr[i - 1] != 0 ) + if( ++ssl->cur_out_ctr[i - 1] != 0 ) break; /* The loop goes to its end iff the counter is wrapping */ @@ -5562,7 +6468,7 @@ int mbedtls_ssl_write_finished( mbedtls_ssl_context *ssl ) } else #endif /* MBEDTLS_SSL_PROTO_DTLS */ - memset( ssl->out_ctr, 0, 8 ); + memset( ssl->cur_out_ctr, 0, 8 ); ssl->transform_out = ssl->transform_negotiate; ssl->session_out = ssl->session_negotiate; @@ -5583,11 +6489,20 @@ int mbedtls_ssl_write_finished( mbedtls_ssl_context *ssl ) mbedtls_ssl_send_flight_completed( ssl ); #endif - if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); + return( ret ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flight_transmit", ret ); return( ret ); } +#endif MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write finished" ) ); @@ -5610,7 +6525,7 @@ int mbedtls_ssl_parse_finished( mbedtls_ssl_context *ssl ) ssl->handshake->calc_finished( ssl, buf, ssl->conf->endpoint ^ 1 ); - if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); return( ret ); @@ -5722,6 +6637,10 @@ static void ssl_handshake_params_init( mbedtls_ssl_handshake_params *handshake ) #endif #endif +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + mbedtls_x509_crt_restart_init( &handshake->ecrs_ctx ); +#endif + #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) handshake->sni_authmode = MBEDTLS_SSL_VERIFY_UNSET; #endif @@ -5841,6 +6760,78 @@ static int ssl_cookie_check_dummy( void *ctx, } #endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY && MBEDTLS_SSL_SRV_C */ +/* Once ssl->out_hdr as the address of the beginning of the + * next outgoing record is set, deduce the other pointers. + * + * Note: For TLS, we save the implicit record sequence number + * (entering MAC computation) in the 8 bytes before ssl->out_hdr, + * and the caller has to make sure there's space for this. + */ + +static void ssl_update_out_pointers( mbedtls_ssl_context *ssl, + mbedtls_ssl_transform *transform ) +{ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + ssl->out_ctr = ssl->out_hdr + 3; + ssl->out_len = ssl->out_hdr + 11; + ssl->out_iv = ssl->out_hdr + 13; + } + else +#endif + { + ssl->out_ctr = ssl->out_hdr - 8; + ssl->out_len = ssl->out_hdr + 3; + ssl->out_iv = ssl->out_hdr + 5; + } + + /* Adjust out_msg to make space for explicit IV, if used. */ + if( transform != NULL && + ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) + { + ssl->out_msg = ssl->out_iv + transform->ivlen - transform->fixed_ivlen; + } + else + ssl->out_msg = ssl->out_iv; +} + +/* Once ssl->in_hdr as the address of the beginning of the + * next incoming record is set, deduce the other pointers. + * + * Note: For TLS, we save the implicit record sequence number + * (entering MAC computation) in the 8 bytes before ssl->in_hdr, + * and the caller has to make sure there's space for this. + */ + +static void ssl_update_in_pointers( mbedtls_ssl_context *ssl, + mbedtls_ssl_transform *transform ) +{ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + ssl->in_ctr = ssl->in_hdr + 3; + ssl->in_len = ssl->in_hdr + 11; + ssl->in_iv = ssl->in_hdr + 13; + } + else +#endif + { + ssl->in_ctr = ssl->in_hdr - 8; + ssl->in_len = ssl->in_hdr + 3; + ssl->in_iv = ssl->in_hdr + 5; + } + + /* Offset in_msg from in_iv to allow space for explicit IV, if used. */ + if( transform != NULL && + ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) + { + ssl->in_msg = ssl->in_iv + transform->ivlen - transform->fixed_ivlen; + } + else + ssl->in_msg = ssl->in_iv; +} + /* * Initialize an SSL context */ @@ -5852,6 +6843,28 @@ void mbedtls_ssl_init( mbedtls_ssl_context *ssl ) /* * Setup an SSL context */ + +static void ssl_reset_in_out_pointers( mbedtls_ssl_context *ssl ) +{ + /* Set the incoming and outgoing record pointers. */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + ssl->out_hdr = ssl->out_buf; + ssl->in_hdr = ssl->in_buf; + } + else +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + { + ssl->out_hdr = ssl->out_buf + 8; + ssl->in_hdr = ssl->in_buf + 8; + } + + /* Derive other internal pointers. */ + ssl_update_out_pointers( ssl, NULL /* no transform enabled */ ); + ssl_update_in_pointers ( ssl, NULL /* no transform enabled */ ); +} + int mbedtls_ssl_setup( mbedtls_ssl_context *ssl, const mbedtls_ssl_config *conf ) { @@ -5862,57 +6875,55 @@ int mbedtls_ssl_setup( mbedtls_ssl_context *ssl, /* * Prepare base structures */ + + /* Set to NULL in case of an error condition */ + ssl->out_buf = NULL; + ssl->in_buf = mbedtls_calloc( 1, MBEDTLS_SSL_IN_BUFFER_LEN ); if( ssl->in_buf == NULL ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", MBEDTLS_SSL_IN_BUFFER_LEN) ); - return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; + goto error; } ssl->out_buf = mbedtls_calloc( 1, MBEDTLS_SSL_OUT_BUFFER_LEN ); if( ssl->out_buf == NULL ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", MBEDTLS_SSL_OUT_BUFFER_LEN) ); - mbedtls_free( ssl->in_buf ); - ssl->in_buf = NULL; - return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); - } - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - ssl->out_hdr = ssl->out_buf; - ssl->out_ctr = ssl->out_buf + 3; - ssl->out_len = ssl->out_buf + 11; - ssl->out_iv = ssl->out_buf + 13; - ssl->out_msg = ssl->out_buf + 13; - - ssl->in_hdr = ssl->in_buf; - ssl->in_ctr = ssl->in_buf + 3; - ssl->in_len = ssl->in_buf + 11; - ssl->in_iv = ssl->in_buf + 13; - ssl->in_msg = ssl->in_buf + 13; + ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; + goto error; } - else -#endif - { - ssl->out_ctr = ssl->out_buf; - ssl->out_hdr = ssl->out_buf + 8; - ssl->out_len = ssl->out_buf + 11; - ssl->out_iv = ssl->out_buf + 13; - ssl->out_msg = ssl->out_buf + 13; - ssl->in_ctr = ssl->in_buf; - ssl->in_hdr = ssl->in_buf + 8; - ssl->in_len = ssl->in_buf + 11; - ssl->in_iv = ssl->in_buf + 13; - ssl->in_msg = ssl->in_buf + 13; - } + ssl_reset_in_out_pointers( ssl ); if( ( ret = ssl_handshake_init( ssl ) ) != 0 ) - return( ret ); + goto error; return( 0 ); + +error: + mbedtls_free( ssl->in_buf ); + mbedtls_free( ssl->out_buf ); + + ssl->conf = NULL; + + ssl->in_buf = NULL; + ssl->out_buf = NULL; + + ssl->in_hdr = NULL; + ssl->in_ctr = NULL; + ssl->in_len = NULL; + ssl->in_iv = NULL; + ssl->in_msg = NULL; + + ssl->out_hdr = NULL; + ssl->out_ctr = NULL; + ssl->out_len = NULL; + ssl->out_iv = NULL; + ssl->out_msg = NULL; + + return( ret ); } /* @@ -5926,6 +6937,11 @@ static int ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial ) { int ret; +#if !defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) || \ + !defined(MBEDTLS_SSL_SRV_C) + ((void) partial); +#endif + ssl->state = MBEDTLS_SSL_HELLO_REQUEST; /* Cancel any possibly running timer */ @@ -5942,12 +6958,10 @@ static int ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial ) ssl->secure_renegotiation = MBEDTLS_SSL_LEGACY_RENEGOTIATION; ssl->in_offt = NULL; + ssl_reset_in_out_pointers( ssl ); - ssl->in_msg = ssl->in_buf + 13; ssl->in_msgtype = 0; ssl->in_msglen = 0; - if( partial == 0 ) - ssl->in_left = 0; #if defined(MBEDTLS_SSL_PROTO_DTLS) ssl->next_record_offset = 0; ssl->in_epoch = 0; @@ -5961,7 +6975,6 @@ static int ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial ) ssl->keep_current_message = 0; - ssl->out_msg = ssl->out_buf + 13; ssl->out_msgtype = 0; ssl->out_msglen = 0; ssl->out_left = 0; @@ -5970,12 +6983,23 @@ static int ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial ) ssl->split_done = 0; #endif + memset( ssl->cur_out_ctr, 0, sizeof( ssl->cur_out_ctr ) ); + ssl->transform_in = NULL; ssl->transform_out = NULL; + ssl->session_in = NULL; + ssl->session_out = NULL; + memset( ssl->out_buf, 0, MBEDTLS_SSL_OUT_BUFFER_LEN ); + +#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C) if( partial == 0 ) +#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */ + { + ssl->in_left = 0; memset( ssl->in_buf, 0, MBEDTLS_SSL_IN_BUFFER_LEN ); + } #if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) if( mbedtls_ssl_hw_record_reset != NULL ) @@ -6008,7 +7032,9 @@ static int ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial ) #endif #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) +#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) if( partial == 0 ) +#endif { mbedtls_free( ssl->cli_id ); ssl->cli_id = NULL; @@ -6059,7 +7085,15 @@ void mbedtls_ssl_conf_dtls_badmac_limit( mbedtls_ssl_config *conf, unsigned limi #endif #if defined(MBEDTLS_SSL_PROTO_DTLS) -void mbedtls_ssl_conf_handshake_timeout( mbedtls_ssl_config *conf, uint32_t min, uint32_t max ) + +void mbedtls_ssl_set_datagram_packing( mbedtls_ssl_context *ssl, + unsigned allow_packing ) +{ + ssl->disable_datagram_packing = !allow_packing; +} + +void mbedtls_ssl_conf_handshake_timeout( mbedtls_ssl_config *conf, + uint32_t min, uint32_t max ) { conf->hs_timeout_min = min; conf->hs_timeout_max = max; @@ -6109,6 +7143,13 @@ void mbedtls_ssl_set_bio( mbedtls_ssl_context *ssl, ssl->f_recv_timeout = f_recv_timeout; } +#if defined(MBEDTLS_SSL_PROTO_DTLS) +void mbedtls_ssl_set_mtu( mbedtls_ssl_context *ssl, uint16_t mtu ) +{ + ssl->mtu = mtu; +} +#endif + void mbedtls_ssl_conf_read_timeout( mbedtls_ssl_config *conf, uint32_t timeout ) { conf->read_timeout = timeout; @@ -6772,7 +7813,7 @@ int mbedtls_ssl_check_pending( const mbedtls_ssl_context *ssl ) /* * In all other cases, the rest of the message can be dropped. - * As in ssl_read_record_layer, this needs to be adapted if + * As in ssl_get_next_record, this needs to be adapted if * we implement support for multiple alerts in single records. */ @@ -6839,28 +7880,47 @@ const char *mbedtls_ssl_get_version( const mbedtls_ssl_context *ssl ) int mbedtls_ssl_get_record_expansion( const mbedtls_ssl_context *ssl ) { - size_t transform_expansion; + size_t transform_expansion = 0; const mbedtls_ssl_transform *transform = ssl->transform_out; + unsigned block_size; + + if( transform == NULL ) + return( (int) mbedtls_ssl_hdr_len( ssl ) ); #if defined(MBEDTLS_ZLIB_SUPPORT) if( ssl->session_out->compression != MBEDTLS_SSL_COMPRESS_NULL ) return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); #endif - if( transform == NULL ) - return( (int) mbedtls_ssl_hdr_len( ssl ) ); - switch( mbedtls_cipher_get_cipher_mode( &transform->cipher_ctx_enc ) ) { case MBEDTLS_MODE_GCM: case MBEDTLS_MODE_CCM: + case MBEDTLS_MODE_CHACHAPOLY: case MBEDTLS_MODE_STREAM: transform_expansion = transform->minlen; break; case MBEDTLS_MODE_CBC: - transform_expansion = transform->maclen - + mbedtls_cipher_get_block_size( &transform->cipher_ctx_enc ); + + block_size = mbedtls_cipher_get_block_size( + &transform->cipher_ctx_enc ); + + /* Expansion due to the addition of the MAC. */ + transform_expansion += transform->maclen; + + /* Expansion due to the addition of CBC padding; + * Theoretically up to 256 bytes, but we never use + * more than the block size of the underlying cipher. */ + transform_expansion += block_size; + + /* For TLS 1.1 or higher, an explicit IV is added + * after the record header. */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) + transform_expansion += block_size; +#endif /* MBEDTLS_SSL_PROTO_TLS1_1 || MBEDTLS_SSL_PROTO_TLS1_2 */ + break; default: @@ -6881,19 +7941,89 @@ size_t mbedtls_ssl_get_max_frag_len( const mbedtls_ssl_context *ssl ) */ max_len = ssl_mfl_code_to_length( ssl->conf->mfl_code ); - /* - * Check if a smaller max length was negotiated - */ + /* Check if a smaller max length was negotiated */ if( ssl->session_out != NULL && ssl_mfl_code_to_length( ssl->session_out->mfl_code ) < max_len ) { max_len = ssl_mfl_code_to_length( ssl->session_out->mfl_code ); } - return max_len; + /* During a handshake, use the value being negotiated */ + if( ssl->session_negotiate != NULL && + ssl_mfl_code_to_length( ssl->session_negotiate->mfl_code ) < max_len ) + { + max_len = ssl_mfl_code_to_length( ssl->session_negotiate->mfl_code ); + } + + return( max_len ); } #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) +static size_t ssl_get_current_mtu( const mbedtls_ssl_context *ssl ) +{ + /* Return unlimited mtu for client hello messages to avoid fragmentation. */ + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT && + ( ssl->state == MBEDTLS_SSL_CLIENT_HELLO || + ssl->state == MBEDTLS_SSL_SERVER_HELLO ) ) + return ( 0 ); + + if( ssl->handshake == NULL || ssl->handshake->mtu == 0 ) + return( ssl->mtu ); + + if( ssl->mtu == 0 ) + return( ssl->handshake->mtu ); + + return( ssl->mtu < ssl->handshake->mtu ? + ssl->mtu : ssl->handshake->mtu ); +} +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +int mbedtls_ssl_get_max_out_record_payload( const mbedtls_ssl_context *ssl ) +{ + size_t max_len = MBEDTLS_SSL_OUT_CONTENT_LEN; + +#if !defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) && \ + !defined(MBEDTLS_SSL_PROTO_DTLS) + (void) ssl; +#endif + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + const size_t mfl = mbedtls_ssl_get_max_frag_len( ssl ); + + if( max_len > mfl ) + max_len = mfl; +#endif + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl_get_current_mtu( ssl ) != 0 ) + { + const size_t mtu = ssl_get_current_mtu( ssl ); + const int ret = mbedtls_ssl_get_record_expansion( ssl ); + const size_t overhead = (size_t) ret; + + if( ret < 0 ) + return( ret ); + + if( mtu <= overhead ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "MTU too low for record expansion" ) ); + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + } + + if( max_len > mtu - overhead ) + max_len = mtu - overhead; + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +#if !defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) && \ + !defined(MBEDTLS_SSL_PROTO_DTLS) + ((void) ssl); +#endif + + return( (int) max_len ); +} + #if defined(MBEDTLS_X509_CRT_PARSE_C) const mbedtls_x509_crt *mbedtls_ssl_get_peer_cert( const mbedtls_ssl_context *ssl ) { @@ -6981,9 +8111,9 @@ static int ssl_write_hello_request( mbedtls_ssl_context *ssl ) ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; ssl->out_msg[0] = MBEDTLS_SSL_HS_HELLO_REQUEST; - if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); return( ret ); } @@ -7113,7 +8243,7 @@ static int ssl_check_ctr_renegotiate( mbedtls_ssl_context *ssl ) in_ctr_cmp = memcmp( ssl->in_ctr + ep_len, ssl->conf->renego_period + ep_len, 8 - ep_len ); - out_ctr_cmp = memcmp( ssl->out_ctr + ep_len, + out_ctr_cmp = memcmp( ssl->cur_out_ctr + ep_len, ssl->conf->renego_period + ep_len, 8 - ep_len ); if( in_ctr_cmp <= 0 && out_ctr_cmp <= 0 ) @@ -7148,7 +8278,7 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ) if( ssl->handshake != NULL && ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING ) { - if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 ) + if( ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 ) return( ret ); } } @@ -7197,7 +8327,7 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ) ssl_set_timer( ssl, ssl->conf->read_timeout ); } - if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) { if( ret == MBEDTLS_ERR_SSL_CONN_EOF ) return( 0 ); @@ -7212,7 +8342,7 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ) /* * OpenSSL sends empty messages to randomize the IV */ - if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) { if( ret == MBEDTLS_ERR_SSL_CONN_EOF ) return( 0 ); @@ -7445,12 +8575,15 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ) static int ssl_write_real( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ) { - int ret; -#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) - size_t max_len = mbedtls_ssl_get_max_frag_len( ssl ); -#else - size_t max_len = MBEDTLS_SSL_OUT_CONTENT_LEN; -#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + int ret = mbedtls_ssl_get_max_out_record_payload( ssl ); + const size_t max_len = (size_t) ret; + + if( ret < 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_get_max_out_record_payload", ret ); + return( ret ); + } + if( len > max_len ) { #if defined(MBEDTLS_SSL_PROTO_DTLS) @@ -7491,7 +8624,7 @@ static int ssl_write_real( mbedtls_ssl_context *ssl, ssl->out_msgtype = MBEDTLS_SSL_MSG_APPLICATION_DATA; memcpy( ssl->out_msg, buf, len ); - if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + if( ( ret = mbedtls_ssl_write_record( ssl, SSL_FORCE_FLUSH ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); return( ret ); @@ -7643,6 +8776,42 @@ static void ssl_key_cert_free( mbedtls_ssl_key_cert *key_cert ) } #endif /* MBEDTLS_X509_CRT_PARSE_C */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + +static void ssl_buffering_free( mbedtls_ssl_context *ssl ) +{ + unsigned offset; + mbedtls_ssl_handshake_params * const hs = ssl->handshake; + + if( hs == NULL ) + return; + + ssl_free_buffered_record( ssl ); + + for( offset = 0; offset < MBEDTLS_SSL_MAX_BUFFERED_HS; offset++ ) + ssl_buffering_free_slot( ssl, offset ); +} + +static void ssl_buffering_free_slot( mbedtls_ssl_context *ssl, + uint8_t slot ) +{ + mbedtls_ssl_handshake_params * const hs = ssl->handshake; + mbedtls_ssl_hs_buffer * const hs_buf = &hs->buffering.hs[slot]; + + if( slot >= MBEDTLS_SSL_MAX_BUFFERED_HS ) + return; + + if( hs_buf->is_valid == 1 ) + { + hs->buffering.total_bytes_buffered -= hs_buf->data_len; + mbedtls_platform_zeroize( hs_buf->data, hs_buf->data_len ); + mbedtls_free( hs_buf->data ); + memset( hs_buf, 0, sizeof( mbedtls_ssl_hs_buffer ) ); + } +} + +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + void mbedtls_ssl_handshake_free( mbedtls_ssl_context *ssl ) { mbedtls_ssl_handshake_params *handshake = ssl->handshake; @@ -7720,10 +8889,14 @@ void mbedtls_ssl_handshake_free( mbedtls_ssl_context *ssl ) } #endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_SERVER_NAME_INDICATION */ +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + mbedtls_x509_crt_restart_free( &handshake->ecrs_ctx ); +#endif + #if defined(MBEDTLS_SSL_PROTO_DTLS) mbedtls_free( handshake->verify_cookie ); - mbedtls_free( handshake->hs_msg ); ssl_flight_free( handshake->flight ); + ssl_buffering_free( ssl ); #endif mbedtls_platform_zeroize( handshake, diff --git a/thirdparty/mbedtls/library/threading.c b/thirdparty/mbedtls/library/threading.c index 7a32e672c7..7c90c7c595 100644 --- a/thirdparty/mbedtls/library/threading.c +++ b/thirdparty/mbedtls/library/threading.c @@ -19,6 +19,14 @@ * This file is part of mbed TLS (https://tls.mbed.org) */ +/* + * Ensure gmtime_r is available even with -std=c99; must be defined before + * config.h, which pulls in glibc's features.h. Harmless on other platforms. + */ +#if !defined(_POSIX_C_SOURCE) +#define _POSIX_C_SOURCE 200112L +#endif + #if !defined(MBEDTLS_CONFIG_FILE) #include "mbedtls/config.h" #else @@ -29,6 +37,36 @@ #include "mbedtls/threading.h" +#if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_PLATFORM_GMTIME_R_ALT) + +#if !defined(_WIN32) && (defined(unix) || \ + defined(__unix) || defined(__unix__) || (defined(__APPLE__) && \ + defined(__MACH__))) +#include <unistd.h> +#endif /* !_WIN32 && (unix || __unix || __unix__ || + * (__APPLE__ && __MACH__)) */ + +#if !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) || \ + ( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) && \ + _POSIX_THREAD_SAFE_FUNCTIONS >= 20112L ) ) +/* + * This is a convenience shorthand macro to avoid checking the long + * preprocessor conditions above. Ideally, we could expose this macro in + * platform_util.h and simply use it in platform_util.c, threading.c and + * threading.h. However, this macro is not part of the Mbed TLS public API, so + * we keep it private by only defining it in this file + */ + +#if ! ( defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) ) +#define THREADING_USE_GMTIME +#endif /* ! ( defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) ) */ + +#endif /* !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) || \ + ( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) && \ + _POSIX_THREAD_SAFE_FUNCTIONS >= 20112L ) ) */ + +#endif /* MBEDTLS_HAVE_TIME_DATE && !MBEDTLS_PLATFORM_GMTIME_R_ALT */ + #if defined(MBEDTLS_THREADING_PTHREAD) static void threading_mutex_init_pthread( mbedtls_threading_mutex_t *mutex ) { @@ -114,6 +152,9 @@ void mbedtls_threading_set_alt( void (*mutex_init)( mbedtls_threading_mutex_t * #if defined(MBEDTLS_FS_IO) mbedtls_mutex_init( &mbedtls_threading_readdir_mutex ); #endif +#if defined(THREADING_USE_GMTIME) + mbedtls_mutex_init( &mbedtls_threading_gmtime_mutex ); +#endif } /* @@ -124,6 +165,9 @@ void mbedtls_threading_free_alt( void ) #if defined(MBEDTLS_FS_IO) mbedtls_mutex_free( &mbedtls_threading_readdir_mutex ); #endif +#if defined(THREADING_USE_GMTIME) + mbedtls_mutex_free( &mbedtls_threading_gmtime_mutex ); +#endif } #endif /* MBEDTLS_THREADING_ALT */ @@ -136,5 +180,8 @@ void mbedtls_threading_free_alt( void ) #if defined(MBEDTLS_FS_IO) mbedtls_threading_mutex_t mbedtls_threading_readdir_mutex MUTEX_INIT; #endif +#if defined(THREADING_USE_GMTIME) +mbedtls_threading_mutex_t mbedtls_threading_gmtime_mutex MUTEX_INIT; +#endif #endif /* MBEDTLS_THREADING_C */ diff --git a/thirdparty/mbedtls/library/timing.c b/thirdparty/mbedtls/library/timing.c index 3e8139f1f9..413d133fb6 100644 --- a/thirdparty/mbedtls/library/timing.c +++ b/thirdparty/mbedtls/library/timing.c @@ -52,6 +52,7 @@ #include <windows.h> #include <winbase.h> +#include <process.h> struct _hr_time { @@ -267,18 +268,17 @@ unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int /* It's OK to use a global because alarm() is supposed to be global anyway */ static DWORD alarmMs; -static DWORD WINAPI TimerProc( LPVOID TimerContext ) +static void TimerProc( void *TimerContext ) { - ((void) TimerContext); + (void) TimerContext; Sleep( alarmMs ); mbedtls_timing_alarmed = 1; - return( TRUE ); + /* _endthread will be called implicitly on return + * That ensures execution of thread funcition's epilogue */ } void mbedtls_set_alarm( int seconds ) { - DWORD ThreadId; - if( seconds == 0 ) { /* No need to create a thread for this simple case. @@ -289,7 +289,7 @@ void mbedtls_set_alarm( int seconds ) mbedtls_timing_alarmed = 0; alarmMs = seconds * 1000; - CloseHandle( CreateThread( NULL, 0, TimerProc, NULL, 0, &ThreadId ) ); + (void) _beginthread( TimerProc, 0, NULL ); } #else /* _WIN32 && !EFIX64 && !EFI32 */ diff --git a/thirdparty/mbedtls/library/version_features.c b/thirdparty/mbedtls/library/version_features.c index 777b6034c4..4c36d3caaa 100644 --- a/thirdparty/mbedtls/library/version_features.c +++ b/thirdparty/mbedtls/library/version_features.c @@ -84,6 +84,9 @@ static const char *features[] = { #if defined(MBEDTLS_DEPRECATED_REMOVED) "MBEDTLS_DEPRECATED_REMOVED", #endif /* MBEDTLS_DEPRECATED_REMOVED */ +#if defined(MBEDTLS_CHECK_PARAMS) + "MBEDTLS_CHECK_PARAMS", +#endif /* MBEDTLS_CHECK_PARAMS */ #if defined(MBEDTLS_TIMING_ALT) "MBEDTLS_TIMING_ALT", #endif /* MBEDTLS_TIMING_ALT */ @@ -339,6 +342,9 @@ static const char *features[] = { #if defined(MBEDTLS_ECP_NIST_OPTIM) "MBEDTLS_ECP_NIST_OPTIM", #endif /* MBEDTLS_ECP_NIST_OPTIM */ +#if defined(MBEDTLS_ECP_RESTARTABLE) + "MBEDTLS_ECP_RESTARTABLE", +#endif /* MBEDTLS_ECP_RESTARTABLE */ #if defined(MBEDTLS_ECDSA_DETERMINISTIC) "MBEDTLS_ECDSA_DETERMINISTIC", #endif /* MBEDTLS_ECDSA_DETERMINISTIC */ diff --git a/thirdparty/mbedtls/library/x509.c b/thirdparty/mbedtls/library/x509.c index 2e6795f750..52b5b649f7 100644 --- a/thirdparty/mbedtls/library/x509.c +++ b/thirdparty/mbedtls/library/x509.c @@ -29,10 +29,6 @@ * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf */ -/* Ensure gmtime_r is available even with -std=c99; must be included before - * config.h, which pulls in glibc's features.h. Harmless on other platforms. */ -#define _POSIX_C_SOURCE 200112L - #if !defined(MBEDTLS_CONFIG_FILE) #include "mbedtls/config.h" #else @@ -67,6 +63,7 @@ #include "mbedtls/platform_time.h" #endif #if defined(MBEDTLS_HAVE_TIME_DATE) +#include "mbedtls/platform_util.h" #include <time.h> #endif @@ -901,11 +898,7 @@ static int x509_get_current_time( mbedtls_x509_time *now ) int ret = 0; tt = mbedtls_time( NULL ); -#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) - lt = gmtime_s( &tm_buf, &tt ) == 0 ? &tm_buf : NULL; -#else - lt = gmtime_r( &tt, &tm_buf ); -#endif + lt = mbedtls_platform_gmtime_r( &tt, &tm_buf ); if( lt == NULL ) ret = -1; diff --git a/thirdparty/mbedtls/library/x509_create.c b/thirdparty/mbedtls/library/x509_create.c index df20ec8ebd..546e8fa1a9 100644 --- a/thirdparty/mbedtls/library/x509_create.c +++ b/thirdparty/mbedtls/library/x509_create.c @@ -33,48 +33,84 @@ #include <string.h> +/* Structure linking OIDs for X.509 DN AttributeTypes to their + * string representations and default string encodings used by Mbed TLS. */ typedef struct { - const char *name; - size_t name_len; - const char*oid; + const char *name; /* String representation of AttributeType, e.g. + * "CN" or "emailAddress". */ + size_t name_len; /* Length of 'name', without trailing 0 byte. */ + const char *oid; /* String representation of OID of AttributeType, + * as per RFC 5280, Appendix A.1. */ + int default_tag; /* The default character encoding used for the + * given attribute type, e.g. + * MBEDTLS_ASN1_UTF8_STRING for UTF-8. */ } x509_attr_descriptor_t; #define ADD_STRLEN( s ) s, sizeof( s ) - 1 +/* X.509 DN attributes from RFC 5280, Appendix A.1. */ static const x509_attr_descriptor_t x509_attrs[] = { - { ADD_STRLEN( "CN" ), MBEDTLS_OID_AT_CN }, - { ADD_STRLEN( "commonName" ), MBEDTLS_OID_AT_CN }, - { ADD_STRLEN( "C" ), MBEDTLS_OID_AT_COUNTRY }, - { ADD_STRLEN( "countryName" ), MBEDTLS_OID_AT_COUNTRY }, - { ADD_STRLEN( "O" ), MBEDTLS_OID_AT_ORGANIZATION }, - { ADD_STRLEN( "organizationName" ), MBEDTLS_OID_AT_ORGANIZATION }, - { ADD_STRLEN( "L" ), MBEDTLS_OID_AT_LOCALITY }, - { ADD_STRLEN( "locality" ), MBEDTLS_OID_AT_LOCALITY }, - { ADD_STRLEN( "R" ), MBEDTLS_OID_PKCS9_EMAIL }, - { ADD_STRLEN( "OU" ), MBEDTLS_OID_AT_ORG_UNIT }, - { ADD_STRLEN( "organizationalUnitName" ), MBEDTLS_OID_AT_ORG_UNIT }, - { ADD_STRLEN( "ST" ), MBEDTLS_OID_AT_STATE }, - { ADD_STRLEN( "stateOrProvinceName" ), MBEDTLS_OID_AT_STATE }, - { ADD_STRLEN( "emailAddress" ), MBEDTLS_OID_PKCS9_EMAIL }, - { ADD_STRLEN( "serialNumber" ), MBEDTLS_OID_AT_SERIAL_NUMBER }, - { ADD_STRLEN( "postalAddress" ), MBEDTLS_OID_AT_POSTAL_ADDRESS }, - { ADD_STRLEN( "postalCode" ), MBEDTLS_OID_AT_POSTAL_CODE }, - { ADD_STRLEN( "dnQualifier" ), MBEDTLS_OID_AT_DN_QUALIFIER }, - { ADD_STRLEN( "title" ), MBEDTLS_OID_AT_TITLE }, - { ADD_STRLEN( "surName" ), MBEDTLS_OID_AT_SUR_NAME }, - { ADD_STRLEN( "SN" ), MBEDTLS_OID_AT_SUR_NAME }, - { ADD_STRLEN( "givenName" ), MBEDTLS_OID_AT_GIVEN_NAME }, - { ADD_STRLEN( "GN" ), MBEDTLS_OID_AT_GIVEN_NAME }, - { ADD_STRLEN( "initials" ), MBEDTLS_OID_AT_INITIALS }, - { ADD_STRLEN( "pseudonym" ), MBEDTLS_OID_AT_PSEUDONYM }, - { ADD_STRLEN( "generationQualifier" ), MBEDTLS_OID_AT_GENERATION_QUALIFIER }, - { ADD_STRLEN( "domainComponent" ), MBEDTLS_OID_DOMAIN_COMPONENT }, - { ADD_STRLEN( "DC" ), MBEDTLS_OID_DOMAIN_COMPONENT }, - { NULL, 0, NULL } + { ADD_STRLEN( "CN" ), + MBEDTLS_OID_AT_CN, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "commonName" ), + MBEDTLS_OID_AT_CN, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "C" ), + MBEDTLS_OID_AT_COUNTRY, MBEDTLS_ASN1_PRINTABLE_STRING }, + { ADD_STRLEN( "countryName" ), + MBEDTLS_OID_AT_COUNTRY, MBEDTLS_ASN1_PRINTABLE_STRING }, + { ADD_STRLEN( "O" ), + MBEDTLS_OID_AT_ORGANIZATION, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "organizationName" ), + MBEDTLS_OID_AT_ORGANIZATION, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "L" ), + MBEDTLS_OID_AT_LOCALITY, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "locality" ), + MBEDTLS_OID_AT_LOCALITY, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "R" ), + MBEDTLS_OID_PKCS9_EMAIL, MBEDTLS_ASN1_IA5_STRING }, + { ADD_STRLEN( "OU" ), + MBEDTLS_OID_AT_ORG_UNIT, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "organizationalUnitName" ), + MBEDTLS_OID_AT_ORG_UNIT, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "ST" ), + MBEDTLS_OID_AT_STATE, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "stateOrProvinceName" ), + MBEDTLS_OID_AT_STATE, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "emailAddress" ), + MBEDTLS_OID_PKCS9_EMAIL, MBEDTLS_ASN1_IA5_STRING }, + { ADD_STRLEN( "serialNumber" ), + MBEDTLS_OID_AT_SERIAL_NUMBER, MBEDTLS_ASN1_PRINTABLE_STRING }, + { ADD_STRLEN( "postalAddress" ), + MBEDTLS_OID_AT_POSTAL_ADDRESS, MBEDTLS_ASN1_PRINTABLE_STRING }, + { ADD_STRLEN( "postalCode" ), + MBEDTLS_OID_AT_POSTAL_CODE, MBEDTLS_ASN1_PRINTABLE_STRING }, + { ADD_STRLEN( "dnQualifier" ), + MBEDTLS_OID_AT_DN_QUALIFIER, MBEDTLS_ASN1_PRINTABLE_STRING }, + { ADD_STRLEN( "title" ), + MBEDTLS_OID_AT_TITLE, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "surName" ), + MBEDTLS_OID_AT_SUR_NAME, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "SN" ), + MBEDTLS_OID_AT_SUR_NAME, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "givenName" ), + MBEDTLS_OID_AT_GIVEN_NAME, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "GN" ), + MBEDTLS_OID_AT_GIVEN_NAME, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "initials" ), + MBEDTLS_OID_AT_INITIALS, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "pseudonym" ), + MBEDTLS_OID_AT_PSEUDONYM, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "generationQualifier" ), + MBEDTLS_OID_AT_GENERATION_QUALIFIER, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "domainComponent" ), + MBEDTLS_OID_DOMAIN_COMPONENT, MBEDTLS_ASN1_IA5_STRING }, + { ADD_STRLEN( "DC" ), + MBEDTLS_OID_DOMAIN_COMPONENT, MBEDTLS_ASN1_IA5_STRING }, + { NULL, 0, NULL, MBEDTLS_ASN1_NULL } }; -static const char *x509_at_oid_from_name( const char *name, size_t name_len ) +static const x509_attr_descriptor_t *x509_attr_descr_from_name( const char *name, size_t name_len ) { const x509_attr_descriptor_t *cur; @@ -83,7 +119,10 @@ static const char *x509_at_oid_from_name( const char *name, size_t name_len ) strncmp( cur->name, name, name_len ) == 0 ) break; - return( cur->oid ); + if ( cur->name == NULL ) + return( NULL ); + + return( cur ); } int mbedtls_x509_string_to_names( mbedtls_asn1_named_data **head, const char *name ) @@ -92,6 +131,7 @@ int mbedtls_x509_string_to_names( mbedtls_asn1_named_data **head, const char *na const char *s = name, *c = s; const char *end = s + strlen( s ); const char *oid = NULL; + const x509_attr_descriptor_t* attr_descr = NULL; int in_tag = 1; char data[MBEDTLS_X509_MAX_DN_NAME_SIZE]; char *d = data; @@ -103,12 +143,13 @@ int mbedtls_x509_string_to_names( mbedtls_asn1_named_data **head, const char *na { if( in_tag && *c == '=' ) { - if( ( oid = x509_at_oid_from_name( s, c - s ) ) == NULL ) + if( ( attr_descr = x509_attr_descr_from_name( s, c - s ) ) == NULL ) { ret = MBEDTLS_ERR_X509_UNKNOWN_OID; goto exit; } + oid = attr_descr->oid; s = c + 1; in_tag = 0; d = data; @@ -127,13 +168,19 @@ int mbedtls_x509_string_to_names( mbedtls_asn1_named_data **head, const char *na } else if( !in_tag && ( *c == ',' || c == end ) ) { - if( mbedtls_asn1_store_named_data( head, oid, strlen( oid ), - (unsigned char *) data, - d - data ) == NULL ) + mbedtls_asn1_named_data* cur = + mbedtls_asn1_store_named_data( head, oid, strlen( oid ), + (unsigned char *) data, + d - data ); + + if(cur == NULL ) { return( MBEDTLS_ERR_X509_ALLOC_FAILED ); } + // set tagType + cur->val.tag = attr_descr->default_tag; + while( c < end && *(c + 1) == ' ' ) c++; @@ -192,46 +239,40 @@ int mbedtls_x509_set_extension( mbedtls_asn1_named_data **head, const char *oid, * * AttributeValue ::= ANY DEFINED BY AttributeType */ -static int x509_write_name( unsigned char **p, unsigned char *start, - const char *oid, size_t oid_len, - const unsigned char *name, size_t name_len ) +static int x509_write_name( unsigned char **p, unsigned char *start, mbedtls_asn1_named_data* cur_name) { int ret; size_t len = 0; - - // Write PrintableString for all except MBEDTLS_OID_PKCS9_EMAIL - // - if( MBEDTLS_OID_SIZE( MBEDTLS_OID_PKCS9_EMAIL ) == oid_len && - memcmp( oid, MBEDTLS_OID_PKCS9_EMAIL, oid_len ) == 0 ) - { - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_ia5_string( p, start, - (const char *) name, - name_len ) ); - } - else - { - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_printable_string( p, start, - (const char *) name, - name_len ) ); - } - + const char *oid = (const char*)cur_name->oid.p; + size_t oid_len = cur_name->oid.len; + const unsigned char *name = cur_name->val.p; + size_t name_len = cur_name->val.len; + + // Write correct string tag and value + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tagged_string( p, start, + cur_name->val.tag, + (const char *) name, + name_len ) ); // Write OID // - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid, oid_len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid, + oid_len ) ); MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, + MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET ) ); return( (int) len ); } int mbedtls_x509_write_names( unsigned char **p, unsigned char *start, - mbedtls_asn1_named_data *first ) + mbedtls_asn1_named_data *first ) { int ret; size_t len = 0; @@ -239,9 +280,7 @@ int mbedtls_x509_write_names( unsigned char **p, unsigned char *start, while( cur != NULL ) { - MBEDTLS_ASN1_CHK_ADD( len, x509_write_name( p, start, (char *) cur->oid.p, - cur->oid.len, - cur->val.p, cur->val.len ) ); + MBEDTLS_ASN1_CHK_ADD( len, x509_write_name( p, start, cur ) ); cur = cur->next; } diff --git a/thirdparty/mbedtls/library/x509_crt.c b/thirdparty/mbedtls/library/x509_crt.c index 3cf1743821..35a134950e 100644 --- a/thirdparty/mbedtls/library/x509_crt.c +++ b/thirdparty/mbedtls/library/x509_crt.c @@ -43,7 +43,6 @@ #include "mbedtls/oid.h" #include "mbedtls/platform_util.h" -#include <stdio.h> #include <string.h> #if defined(MBEDTLS_PEM_PARSE_C) @@ -53,6 +52,7 @@ #if defined(MBEDTLS_PLATFORM_C) #include "mbedtls/platform.h" #else +#include <stdio.h> #include <stdlib.h> #define mbedtls_free free #define mbedtls_calloc calloc @@ -176,6 +176,9 @@ const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_suiteb = static int x509_profile_check_md_alg( const mbedtls_x509_crt_profile *profile, mbedtls_md_type_t md_alg ) { + if( md_alg == MBEDTLS_MD_NONE ) + return( -1 ); + if( ( profile->allowed_mds & MBEDTLS_X509_ID_FLAG( md_alg ) ) != 0 ) return( 0 ); @@ -189,6 +192,9 @@ static int x509_profile_check_md_alg( const mbedtls_x509_crt_profile *profile, static int x509_profile_check_pk_alg( const mbedtls_x509_crt_profile *profile, mbedtls_pk_type_t pk_alg ) { + if( pk_alg == MBEDTLS_PK_NONE ) + return( -1 ); + if( ( profile->allowed_pks & MBEDTLS_X509_ID_FLAG( pk_alg ) ) != 0 ) return( 0 ); @@ -221,6 +227,9 @@ static int x509_profile_check_key( const mbedtls_x509_crt_profile *profile, { const mbedtls_ecp_group_id gid = mbedtls_pk_ec( *pk )->grp.id; + if( gid == MBEDTLS_ECP_DP_NONE ) + return( -1 ); + if( ( profile->allowed_curves & MBEDTLS_X509_ID_FLAG( gid ) ) != 0 ) return( 0 ); @@ -232,6 +241,153 @@ static int x509_profile_check_key( const mbedtls_x509_crt_profile *profile, } /* + * Like memcmp, but case-insensitive and always returns -1 if different + */ +static int x509_memcasecmp( const void *s1, const void *s2, size_t len ) +{ + size_t i; + unsigned char diff; + const unsigned char *n1 = s1, *n2 = s2; + + for( i = 0; i < len; i++ ) + { + diff = n1[i] ^ n2[i]; + + if( diff == 0 ) + continue; + + if( diff == 32 && + ( ( n1[i] >= 'a' && n1[i] <= 'z' ) || + ( n1[i] >= 'A' && n1[i] <= 'Z' ) ) ) + { + continue; + } + + return( -1 ); + } + + return( 0 ); +} + +/* + * Return 0 if name matches wildcard, -1 otherwise + */ +static int x509_check_wildcard( const char *cn, const mbedtls_x509_buf *name ) +{ + size_t i; + size_t cn_idx = 0, cn_len = strlen( cn ); + + /* We can't have a match if there is no wildcard to match */ + if( name->len < 3 || name->p[0] != '*' || name->p[1] != '.' ) + return( -1 ); + + for( i = 0; i < cn_len; ++i ) + { + if( cn[i] == '.' ) + { + cn_idx = i; + break; + } + } + + if( cn_idx == 0 ) + return( -1 ); + + if( cn_len - cn_idx == name->len - 1 && + x509_memcasecmp( name->p + 1, cn + cn_idx, name->len - 1 ) == 0 ) + { + return( 0 ); + } + + return( -1 ); +} + +/* + * Compare two X.509 strings, case-insensitive, and allowing for some encoding + * variations (but not all). + * + * Return 0 if equal, -1 otherwise. + */ +static int x509_string_cmp( const mbedtls_x509_buf *a, const mbedtls_x509_buf *b ) +{ + if( a->tag == b->tag && + a->len == b->len && + memcmp( a->p, b->p, b->len ) == 0 ) + { + return( 0 ); + } + + if( ( a->tag == MBEDTLS_ASN1_UTF8_STRING || a->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) && + ( b->tag == MBEDTLS_ASN1_UTF8_STRING || b->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) && + a->len == b->len && + x509_memcasecmp( a->p, b->p, b->len ) == 0 ) + { + return( 0 ); + } + + return( -1 ); +} + +/* + * Compare two X.509 Names (aka rdnSequence). + * + * See RFC 5280 section 7.1, though we don't implement the whole algorithm: + * we sometimes return unequal when the full algorithm would return equal, + * but never the other way. (In particular, we don't do Unicode normalisation + * or space folding.) + * + * Return 0 if equal, -1 otherwise. + */ +static int x509_name_cmp( const mbedtls_x509_name *a, const mbedtls_x509_name *b ) +{ + /* Avoid recursion, it might not be optimised by the compiler */ + while( a != NULL || b != NULL ) + { + if( a == NULL || b == NULL ) + return( -1 ); + + /* type */ + if( a->oid.tag != b->oid.tag || + a->oid.len != b->oid.len || + memcmp( a->oid.p, b->oid.p, b->oid.len ) != 0 ) + { + return( -1 ); + } + + /* value */ + if( x509_string_cmp( &a->val, &b->val ) != 0 ) + return( -1 ); + + /* structure of the list of sets */ + if( a->next_merged != b->next_merged ) + return( -1 ); + + a = a->next; + b = b->next; + } + + /* a == NULL == b */ + return( 0 ); +} + +/* + * Reset (init or clear) a verify_chain + */ +static void x509_crt_verify_chain_reset( + mbedtls_x509_crt_verify_chain *ver_chain ) +{ + size_t i; + + for( i = 0; i < MBEDTLS_X509_MAX_VERIFY_CHAIN_SIZE; i++ ) + { + ver_chain->items[i].crt = NULL; + ver_chain->items[i].flags = -1; + } + + ver_chain->len = 0; +} + +/* * Version ::= INTEGER { v1(0), v2(1), v3(2) } */ static int x509_get_version( unsigned char **p, @@ -583,18 +739,14 @@ static int x509_get_crt_ext( unsigned char **p, end_ext_data = *p + len; /* Get extension ID */ - extn_oid.tag = **p; - - if( ( ret = mbedtls_asn1_get_tag( p, end, &extn_oid.len, MBEDTLS_ASN1_OID ) ) != 0 ) + if( ( ret = mbedtls_asn1_get_tag( p, end_ext_data, &extn_oid.len, + MBEDTLS_ASN1_OID ) ) != 0 ) return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + extn_oid.tag = MBEDTLS_ASN1_OID; extn_oid.p = *p; *p += extn_oid.len; - if( ( end - *p ) < 1 ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + - MBEDTLS_ERR_ASN1_OUT_OF_DATA ); - /* Get optional critical */ if( ( ret = mbedtls_asn1_get_bool( p, end_ext_data, &is_critical ) ) != 0 && ( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) ) @@ -1139,7 +1291,7 @@ int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path ) char filename[MAX_PATH]; char *p; size_t len = strlen( path ); - int length_as_int = 0; + int lengthAsInt = 0; WIN32_FIND_DATAW file_data; HANDLE hFind; @@ -1154,7 +1306,7 @@ int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path ) p = filename + len; filename[len++] = '*'; - if ( FAILED ( SizeTToInt( len, &length_as_int ) ) ) + if ( FAILED ( SizeTToInt( len, &lengthAsInt ) ) ) return( MBEDTLS_ERR_X509_FILE_IO_ERROR ); /* @@ -1165,7 +1317,7 @@ int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path ) * incoming string are less than MAX_PATH to avoid a buffer overrun with * MultiByteToWideChar(). */ - w_ret = MultiByteToWideChar( CP_ACP, 0, filename, length_as_int, szDir, + w_ret = MultiByteToWideChar( CP_ACP, 0, filename, lengthAsInt, szDir, MAX_PATH - 3 ); if( w_ret == 0 ) return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); @@ -1182,11 +1334,11 @@ int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path ) if( file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) continue; - if ( FAILED( SizeTToInt( wcslen( file_data.cFileName ), &length_as_int ) ) ) + if ( FAILED( SizeTToInt( wcslen( file_data.cFileName ), &lengthAsInt ) ) ) return( MBEDTLS_ERR_X509_FILE_IO_ERROR ); w_ret = WideCharToMultiByte( CP_ACP, 0, file_data.cFileName, - length_as_int, + lengthAsInt, p, (int) len - 1, NULL, NULL ); if( w_ret == 0 ) @@ -1690,9 +1842,7 @@ static int x509_crt_verifycrl( mbedtls_x509_crt *crt, mbedtls_x509_crt *ca, while( crl_list != NULL ) { if( crl_list->version == 0 || - crl_list->issuer_raw.len != ca->subject_raw.len || - memcmp( crl_list->issuer_raw.p, ca->subject_raw.p, - crl_list->issuer_raw.len ) != 0 ) + x509_name_cmp( &crl_list->issuer, &ca->subject ) != 0 ) { crl_list = crl_list->next; continue; @@ -1702,7 +1852,8 @@ static int x509_crt_verifycrl( mbedtls_x509_crt *crt, mbedtls_x509_crt *ca, * Check if the CA is configured to sign CRLs */ #if defined(MBEDTLS_X509_CHECK_KEY_USAGE) - if( mbedtls_x509_crt_check_key_usage( ca, MBEDTLS_X509_KU_CRL_SIGN ) != 0 ) + if( mbedtls_x509_crt_check_key_usage( ca, + MBEDTLS_X509_KU_CRL_SIGN ) != 0 ) { flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED; break; @@ -1763,140 +1914,11 @@ static int x509_crt_verifycrl( mbedtls_x509_crt *crt, mbedtls_x509_crt *ca, #endif /* MBEDTLS_X509_CRL_PARSE_C */ /* - * Like memcmp, but case-insensitive and always returns -1 if different - */ -static int x509_memcasecmp( const void *s1, const void *s2, size_t len ) -{ - size_t i; - unsigned char diff; - const unsigned char *n1 = s1, *n2 = s2; - - for( i = 0; i < len; i++ ) - { - diff = n1[i] ^ n2[i]; - - if( diff == 0 ) - continue; - - if( diff == 32 && - ( ( n1[i] >= 'a' && n1[i] <= 'z' ) || - ( n1[i] >= 'A' && n1[i] <= 'Z' ) ) ) - { - continue; - } - - return( -1 ); - } - - return( 0 ); -} - -/* - * Return 0 if name matches wildcard, -1 otherwise - */ -static int x509_check_wildcard( const char *cn, const mbedtls_x509_buf *name ) -{ - size_t i; - size_t cn_idx = 0, cn_len = strlen( cn ); - - /* We can't have a match if there is no wildcard to match */ - if( name->len < 3 || name->p[0] != '*' || name->p[1] != '.' ) - return( -1 ); - - for( i = 0; i < cn_len; ++i ) - { - if( cn[i] == '.' ) - { - cn_idx = i; - break; - } - } - - if( cn_idx == 0 ) - return( -1 ); - - if( cn_len - cn_idx == name->len - 1 && - x509_memcasecmp( name->p + 1, cn + cn_idx, name->len - 1 ) == 0 ) - { - return( 0 ); - } - - return( -1 ); -} - -/* - * Compare two X.509 strings, case-insensitive, and allowing for some encoding - * variations (but not all). - * - * Return 0 if equal, -1 otherwise. - */ -static int x509_string_cmp( const mbedtls_x509_buf *a, const mbedtls_x509_buf *b ) -{ - if( a->tag == b->tag && - a->len == b->len && - memcmp( a->p, b->p, b->len ) == 0 ) - { - return( 0 ); - } - - if( ( a->tag == MBEDTLS_ASN1_UTF8_STRING || a->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) && - ( b->tag == MBEDTLS_ASN1_UTF8_STRING || b->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) && - a->len == b->len && - x509_memcasecmp( a->p, b->p, b->len ) == 0 ) - { - return( 0 ); - } - - return( -1 ); -} - -/* - * Compare two X.509 Names (aka rdnSequence). - * - * See RFC 5280 section 7.1, though we don't implement the whole algorithm: - * we sometimes return unequal when the full algorithm would return equal, - * but never the other way. (In particular, we don't do Unicode normalisation - * or space folding.) - * - * Return 0 if equal, -1 otherwise. - */ -static int x509_name_cmp( const mbedtls_x509_name *a, const mbedtls_x509_name *b ) -{ - /* Avoid recursion, it might not be optimised by the compiler */ - while( a != NULL || b != NULL ) - { - if( a == NULL || b == NULL ) - return( -1 ); - - /* type */ - if( a->oid.tag != b->oid.tag || - a->oid.len != b->oid.len || - memcmp( a->oid.p, b->oid.p, b->oid.len ) != 0 ) - { - return( -1 ); - } - - /* value */ - if( x509_string_cmp( &a->val, &b->val ) != 0 ) - return( -1 ); - - /* structure of the list of sets */ - if( a->next_merged != b->next_merged ) - return( -1 ); - - a = a->next; - b = b->next; - } - - /* a == NULL == b */ - return( 0 ); -} - -/* * Check the signature of a certificate by its parent */ static int x509_crt_check_signature( const mbedtls_x509_crt *child, - mbedtls_x509_crt *parent ) + mbedtls_x509_crt *parent, + mbedtls_x509_crt_restart_ctx *rs_ctx ) { const mbedtls_md_info_t *md_info; unsigned char hash[MBEDTLS_MD_MAX_SIZE]; @@ -1908,14 +1930,24 @@ static int x509_crt_check_signature( const mbedtls_x509_crt *child, return( -1 ); } - if( mbedtls_pk_verify_ext( child->sig_pk, child->sig_opts, &parent->pk, - child->sig_md, hash, mbedtls_md_get_size( md_info ), - child->sig.p, child->sig.len ) != 0 ) - { + /* Skip expensive computation on obvious mismatch */ + if( ! mbedtls_pk_can_do( &parent->pk, child->sig_pk ) ) return( -1 ); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && child->sig_pk == MBEDTLS_PK_ECDSA ) + { + return( mbedtls_pk_verify_restartable( &parent->pk, + child->sig_md, hash, mbedtls_md_get_size( md_info ), + child->sig.p, child->sig.len, &rs_ctx->pk ) ); } +#else + (void) rs_ctx; +#endif - return( 0 ); + return( mbedtls_pk_verify_ext( child->sig_pk, child->sig_opts, &parent->pk, + child->sig_md, hash, mbedtls_md_get_size( md_info ), + child->sig.p, child->sig.len ) ); } /* @@ -1962,6 +1994,7 @@ static int x509_crt_check_parent( const mbedtls_x509_crt *child, * 1. subject name matches child's issuer * 2. if necessary, the CA bit is set and key usage allows signing certs * 3. for trusted roots, the signature is correct + * (for intermediates, the signature is checked and the result reported) * 4. pathlen constraints are satisfied * * If there's a suitable candidate which is also time-valid, return the first @@ -1984,23 +2017,54 @@ static int x509_crt_check_parent( const mbedtls_x509_crt *child, * Arguments: * - [in] child: certificate for which we're looking for a parent * - [in] candidates: chained list of potential parents + * - [out] r_parent: parent found (or NULL) + * - [out] r_signature_is_good: 1 if child signature by parent is valid, or 0 * - [in] top: 1 if candidates consists of trusted roots, ie we're at the top * of the chain, 0 otherwise * - [in] path_cnt: number of intermediates seen so far * - [in] self_cnt: number of self-signed intermediates seen so far * (will never be greater than path_cnt) + * - [in-out] rs_ctx: context for restarting operations * * Return value: - * - the first suitable parent found (see above regarding time-validity) - * - NULL if no suitable parent was found + * - 0 on success + * - MBEDTLS_ERR_ECP_IN_PROGRESS otherwise */ -static mbedtls_x509_crt *x509_crt_find_parent_in( mbedtls_x509_crt *child, - mbedtls_x509_crt *candidates, - int top, - size_t path_cnt, - size_t self_cnt ) +static int x509_crt_find_parent_in( + mbedtls_x509_crt *child, + mbedtls_x509_crt *candidates, + mbedtls_x509_crt **r_parent, + int *r_signature_is_good, + int top, + unsigned path_cnt, + unsigned self_cnt, + mbedtls_x509_crt_restart_ctx *rs_ctx ) { - mbedtls_x509_crt *parent, *badtime_parent = NULL; + int ret; + mbedtls_x509_crt *parent, *fallback_parent; + int signature_is_good, fallback_signature_is_good; + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + /* did we have something in progress? */ + if( rs_ctx != NULL && rs_ctx->parent != NULL ) + { + /* restore saved state */ + parent = rs_ctx->parent; + fallback_parent = rs_ctx->fallback_parent; + fallback_signature_is_good = rs_ctx->fallback_signature_is_good; + + /* clear saved state */ + rs_ctx->parent = NULL; + rs_ctx->fallback_parent = NULL; + rs_ctx->fallback_signature_is_good = 0; + + /* resume where we left */ + goto check_signature; + } +#endif + + fallback_parent = NULL; + fallback_signature_is_good = 0; for( parent = candidates; parent != NULL; parent = parent->next ) { @@ -2016,17 +2080,38 @@ static mbedtls_x509_crt *x509_crt_find_parent_in( mbedtls_x509_crt *child, } /* Signature */ - if( top && x509_crt_check_signature( child, parent ) != 0 ) +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +check_signature: +#endif + ret = x509_crt_check_signature( child, parent, rs_ctx ); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) { - continue; + /* save state */ + rs_ctx->parent = parent; + rs_ctx->fallback_parent = fallback_parent; + rs_ctx->fallback_signature_is_good = fallback_signature_is_good; + + return( ret ); } +#else + (void) ret; +#endif + + signature_is_good = ret == 0; + if( top && ! signature_is_good ) + continue; /* optional time check */ if( mbedtls_x509_time_is_past( &parent->valid_to ) || mbedtls_x509_time_is_future( &parent->valid_from ) ) { - if( badtime_parent == NULL ) - badtime_parent = parent; + if( fallback_parent == NULL ) + { + fallback_parent = parent; + fallback_signature_is_good = signature_is_good; + } continue; } @@ -2034,10 +2119,18 @@ static mbedtls_x509_crt *x509_crt_find_parent_in( mbedtls_x509_crt *child, break; } - if( parent == NULL ) - parent = badtime_parent; + if( parent != NULL ) + { + *r_parent = parent; + *r_signature_is_good = signature_is_good; + } + else + { + *r_parent = fallback_parent; + *r_signature_is_good = fallback_signature_is_good; + } - return( parent ); + return( 0 ); } /* @@ -2049,34 +2142,78 @@ static mbedtls_x509_crt *x509_crt_find_parent_in( mbedtls_x509_crt *child, * Arguments: * - [in] child: certificate for which we're looking for a parent, followed * by a chain of possible intermediates - * - [in] trust_ca: locally trusted CAs - * - [out] 1 if parent was found in trust_ca, 0 if found in provided chain - * - [in] path_cnt: number of intermediates seen so far - * - [in] self_cnt: number of self-signed intermediates seen so far + * - [in] trust_ca: list of locally trusted certificates + * - [out] parent: parent found (or NULL) + * - [out] parent_is_trusted: 1 if returned `parent` is trusted, or 0 + * - [out] signature_is_good: 1 if child signature by parent is valid, or 0 + * - [in] path_cnt: number of links in the chain so far (EE -> ... -> child) + * - [in] self_cnt: number of self-signed certs in the chain so far * (will always be no greater than path_cnt) + * - [in-out] rs_ctx: context for restarting operations * * Return value: - * - the first suitable parent found (see find_parent_in() for "suitable") - * - NULL if no suitable parent was found + * - 0 on success + * - MBEDTLS_ERR_ECP_IN_PROGRESS otherwise */ -static mbedtls_x509_crt *x509_crt_find_parent( mbedtls_x509_crt *child, - mbedtls_x509_crt *trust_ca, - int *parent_is_trusted, - size_t path_cnt, - size_t self_cnt ) +static int x509_crt_find_parent( + mbedtls_x509_crt *child, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crt **parent, + int *parent_is_trusted, + int *signature_is_good, + unsigned path_cnt, + unsigned self_cnt, + mbedtls_x509_crt_restart_ctx *rs_ctx ) { - mbedtls_x509_crt *parent; + int ret; + mbedtls_x509_crt *search_list; - /* Look for a parent in trusted CAs */ *parent_is_trusted = 1; - parent = x509_crt_find_parent_in( child, trust_ca, 1, path_cnt, self_cnt ); - if( parent != NULL ) - return( parent ); +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + /* restore then clear saved state if we have some stored */ + if( rs_ctx != NULL && rs_ctx->parent_is_trusted != -1 ) + { + *parent_is_trusted = rs_ctx->parent_is_trusted; + rs_ctx->parent_is_trusted = -1; + } +#endif + + while( 1 ) { + search_list = *parent_is_trusted ? trust_ca : child->next; + + ret = x509_crt_find_parent_in( child, search_list, + parent, signature_is_good, + *parent_is_trusted, + path_cnt, self_cnt, rs_ctx ); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + { + /* save state */ + rs_ctx->parent_is_trusted = *parent_is_trusted; + return( ret ); + } +#else + (void) ret; +#endif + + /* stop here if found or already in second iteration */ + if( *parent != NULL || *parent_is_trusted == 0 ) + break; + + /* prepare second iteration */ + *parent_is_trusted = 0; + } + + /* extra precaution against mistakes in the caller */ + if( *parent == NULL ) + { + *parent_is_trusted = 0; + *signature_is_good = 0; + } - /* Look for a parent upwards the chain */ - *parent_is_trusted = 0; - return( x509_crt_find_parent_in( child, child->next, 0, path_cnt, self_cnt ) ); + return( 0 ); } /* @@ -2125,11 +2262,24 @@ static int x509_crt_check_ee_locally_trusted( * - EE, Ci1, ..., Ciq cannot be continued with a trusted root * -> return that chain with NOT_TRUSTED set on Ciq * + * Tests for (aspects of) this function should include at least: + * - trusted EE + * - EE -> trusted root + * - EE -> intermedate CA -> trusted root + * - if relevant: EE untrusted + * - if relevant: EE -> intermediate, untrusted + * with the aspect under test checked at each relevant level (EE, int, root). + * For some aspects longer chains are required, but usually length 2 is + * enough (but length 1 is not in general). + * * Arguments: * - [in] crt: the cert list EE, C1, ..., Cn * - [in] trust_ca: the trusted list R1, ..., Rp * - [in] ca_crl, profile: as in verify_with_profile() - * - [out] ver_chain, chain_len: the built and verified chain + * - [out] ver_chain: the built and verified chain + * Only valid when return value is 0, may contain garbage otherwise! + * Restart note: need not be the same when calling again to resume. + * - [in-out] rs_ctx: context for restarting operations * * Return value: * - non-zero if the chain could not be fully built and examined @@ -2141,24 +2291,50 @@ static int x509_crt_verify_chain( mbedtls_x509_crt *trust_ca, mbedtls_x509_crl *ca_crl, const mbedtls_x509_crt_profile *profile, - x509_crt_verify_chain_item ver_chain[X509_MAX_VERIFY_CHAIN_SIZE], - size_t *chain_len ) + mbedtls_x509_crt_verify_chain *ver_chain, + mbedtls_x509_crt_restart_ctx *rs_ctx ) { + /* Don't initialize any of those variables here, so that the compiler can + * catch potential issues with jumping ahead when restarting */ + int ret; uint32_t *flags; + mbedtls_x509_crt_verify_chain_item *cur; mbedtls_x509_crt *child; mbedtls_x509_crt *parent; - int parent_is_trusted = 0; - int child_is_trusted = 0; - size_t self_cnt = 0; + int parent_is_trusted; + int child_is_trusted; + int signature_is_good; + unsigned self_cnt; + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + /* resume if we had an operation in progress */ + if( rs_ctx != NULL && rs_ctx->in_progress == x509_crt_rs_find_parent ) + { + /* restore saved state */ + *ver_chain = rs_ctx->ver_chain; /* struct copy */ + self_cnt = rs_ctx->self_cnt; + + /* restore derived state */ + cur = &ver_chain->items[ver_chain->len - 1]; + child = cur->crt; + flags = &cur->flags; + + goto find_parent; + } +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ child = crt; - *chain_len = 0; + self_cnt = 0; + parent_is_trusted = 0; + child_is_trusted = 0; while( 1 ) { /* Add certificate to the verification chain */ - ver_chain[*chain_len].crt = child; - flags = &ver_chain[*chain_len].flags; - ++*chain_len; + cur = &ver_chain->items[ver_chain->len]; + cur->crt = child; + cur->flags = 0; + ver_chain->len++; + flags = &cur->flags; /* Check time-validity (all certificates) */ if( mbedtls_x509_time_is_past( &child->valid_to ) ) @@ -2179,15 +2355,33 @@ static int x509_crt_verify_chain( *flags |= MBEDTLS_X509_BADCERT_BAD_PK; /* Special case: EE certs that are locally trusted */ - if( *chain_len == 1 && + if( ver_chain->len == 1 && x509_crt_check_ee_locally_trusted( child, trust_ca ) == 0 ) { return( 0 ); } +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +find_parent: +#endif /* Look for a parent in trusted CAs or up the chain */ - parent = x509_crt_find_parent( child, trust_ca, &parent_is_trusted, - *chain_len - 1, self_cnt ); + ret = x509_crt_find_parent( child, trust_ca, &parent, + &parent_is_trusted, &signature_is_good, + ver_chain->len - 1, self_cnt, rs_ctx ); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + { + /* save state */ + rs_ctx->in_progress = x509_crt_rs_find_parent; + rs_ctx->self_cnt = self_cnt; + rs_ctx->ver_chain = *ver_chain; /* struct copy */ + + return( ret ); + } +#else + (void) ret; +#endif /* No parent? We're done here */ if( parent == NULL ) @@ -2199,7 +2393,7 @@ static int x509_crt_verify_chain( /* Count intermediate self-issued (not necessarily self-signed) certs. * These can occur with some strategies for key rollover, see [SIRO], * and should be excluded from max_pathlen checks. */ - if( *chain_len != 1 && + if( ver_chain->len != 1 && x509_name_cmp( &child->issuer, &child->subject ) == 0 ) { self_cnt++; @@ -2208,14 +2402,14 @@ static int x509_crt_verify_chain( /* path_cnt is 0 for the first intermediate CA, * and if parent is trusted it's not an intermediate CA */ if( ! parent_is_trusted && - *chain_len > MBEDTLS_X509_MAX_INTERMEDIATE_CA ) + ver_chain->len > MBEDTLS_X509_MAX_INTERMEDIATE_CA ) { /* return immediately to avoid overflow the chain array */ return( MBEDTLS_ERR_X509_FATAL_ERROR ); } - /* if parent is trusted, the signature was checked by find_parent() */ - if( ! parent_is_trusted && x509_crt_check_signature( child, parent ) != 0 ) + /* signature was checked while searching parent */ + if( ! signature_is_good ) *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED; /* check size of signing key */ @@ -2233,6 +2427,7 @@ static int x509_crt_verify_chain( child = parent; parent = NULL; child_is_trusted = parent_is_trusted; + signature_is_good = 0; } } @@ -2301,21 +2496,22 @@ static void x509_crt_verify_name( const mbedtls_x509_crt *crt, */ static int x509_crt_merge_flags_with_cb( uint32_t *flags, - x509_crt_verify_chain_item ver_chain[X509_MAX_VERIFY_CHAIN_SIZE], - size_t chain_len, + const mbedtls_x509_crt_verify_chain *ver_chain, int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), void *p_vrfy ) { int ret; - size_t i; + unsigned i; uint32_t cur_flags; + const mbedtls_x509_crt_verify_chain_item *cur; - for( i = chain_len; i != 0; --i ) + for( i = ver_chain->len; i != 0; --i ) { - cur_flags = ver_chain[i-1].flags; + cur = &ver_chain->items[i-1]; + cur_flags = cur->flags; if( NULL != f_vrfy ) - if( ( ret = f_vrfy( p_vrfy, ver_chain[i-1].crt, (int) i-1, &cur_flags ) ) != 0 ) + if( ( ret = f_vrfy( p_vrfy, cur->crt, (int) i-1, &cur_flags ) ) != 0 ) return( ret ); *flags |= cur_flags; @@ -2325,7 +2521,7 @@ static int x509_crt_merge_flags_with_cb( } /* - * Verify the certificate validity + * Verify the certificate validity (default profile, not restartable) */ int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt, mbedtls_x509_crt *trust_ca, @@ -2334,12 +2530,28 @@ int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt, int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), void *p_vrfy ) { - return( mbedtls_x509_crt_verify_with_profile( crt, trust_ca, ca_crl, - &mbedtls_x509_crt_profile_default, cn, flags, f_vrfy, p_vrfy ) ); + return( mbedtls_x509_crt_verify_restartable( crt, trust_ca, ca_crl, + &mbedtls_x509_crt_profile_default, cn, flags, + f_vrfy, p_vrfy, NULL ) ); +} + +/* + * Verify the certificate validity (user-chosen profile, not restartable) + */ +int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + const mbedtls_x509_crt_profile *profile, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ) +{ + return( mbedtls_x509_crt_verify_restartable( crt, trust_ca, ca_crl, + profile, cn, flags, f_vrfy, p_vrfy, NULL ) ); } /* - * Verify the certificate validity, with profile + * Verify the certificate validity, with profile, restartable version * * This function: * - checks the requested CN (if any) @@ -2348,23 +2560,23 @@ int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt, * - builds and verifies the chain * - then calls the callback and merges the flags */ -int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt, +int mbedtls_x509_crt_verify_restartable( mbedtls_x509_crt *crt, mbedtls_x509_crt *trust_ca, mbedtls_x509_crl *ca_crl, const mbedtls_x509_crt_profile *profile, const char *cn, uint32_t *flags, int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), - void *p_vrfy ) + void *p_vrfy, + mbedtls_x509_crt_restart_ctx *rs_ctx ) { int ret; mbedtls_pk_type_t pk_type; - x509_crt_verify_chain_item ver_chain[X509_MAX_VERIFY_CHAIN_SIZE]; - size_t chain_len; - uint32_t *ee_flags = &ver_chain[0].flags; + mbedtls_x509_crt_verify_chain ver_chain; + uint32_t ee_flags; *flags = 0; - memset( ver_chain, 0, sizeof( ver_chain ) ); - chain_len = 0; + ee_flags = 0; + x509_crt_verify_chain_reset( &ver_chain ); if( profile == NULL ) { @@ -2374,28 +2586,36 @@ int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt, /* check name if requested */ if( cn != NULL ) - x509_crt_verify_name( crt, cn, ee_flags ); + x509_crt_verify_name( crt, cn, &ee_flags ); /* Check the type and size of the key */ pk_type = mbedtls_pk_get_type( &crt->pk ); if( x509_profile_check_pk_alg( profile, pk_type ) != 0 ) - *ee_flags |= MBEDTLS_X509_BADCERT_BAD_PK; + ee_flags |= MBEDTLS_X509_BADCERT_BAD_PK; if( x509_profile_check_key( profile, &crt->pk ) != 0 ) - *ee_flags |= MBEDTLS_X509_BADCERT_BAD_KEY; + ee_flags |= MBEDTLS_X509_BADCERT_BAD_KEY; /* Check the chain */ ret = x509_crt_verify_chain( crt, trust_ca, ca_crl, profile, - ver_chain, &chain_len ); + &ver_chain, rs_ctx ); + if( ret != 0 ) goto exit; + /* Merge end-entity flags */ + ver_chain.items[0].flags |= ee_flags; + /* Build final flags, calling callback on the way if any */ - ret = x509_crt_merge_flags_with_cb( flags, - ver_chain, chain_len, f_vrfy, p_vrfy ); + ret = x509_crt_merge_flags_with_cb( flags, &ver_chain, f_vrfy, p_vrfy ); exit: +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) + mbedtls_x509_crt_restart_free( rs_ctx ); +#endif + /* prevent misuse of the vrfy callback - VERIFY_FAILED would be ignored by * the SSL module for authmode optional, but non-zero return from the * callback means a fatal error so it shouldn't be ignored */ @@ -2506,4 +2726,36 @@ void mbedtls_x509_crt_free( mbedtls_x509_crt *crt ) while( cert_cur != NULL ); } +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +/* + * Initialize a restart context + */ +void mbedtls_x509_crt_restart_init( mbedtls_x509_crt_restart_ctx *ctx ) +{ + mbedtls_pk_restart_init( &ctx->pk ); + + ctx->parent = NULL; + ctx->fallback_parent = NULL; + ctx->fallback_signature_is_good = 0; + + ctx->parent_is_trusted = -1; + + ctx->in_progress = x509_crt_rs_none; + ctx->self_cnt = 0; + x509_crt_verify_chain_reset( &ctx->ver_chain ); +} + +/* + * Free the components of a restart context + */ +void mbedtls_x509_crt_restart_free( mbedtls_x509_crt_restart_ctx *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_pk_restart_free( &ctx->pk ); + mbedtls_x509_crt_restart_init( ctx ); +} +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + #endif /* MBEDTLS_X509_CRT_PARSE_C */ diff --git a/thirdparty/rtaudio/RtAudio.cpp b/thirdparty/rtaudio/RtAudio.cpp deleted file mode 100644 index 04159776f7..0000000000 --- a/thirdparty/rtaudio/RtAudio.cpp +++ /dev/null @@ -1,10232 +0,0 @@ -#ifdef RTAUDIO_ENABLED // -GODOT- - -/************************************************************************/ -/*! \class RtAudio - \brief Realtime audio i/o C++ classes. - - RtAudio provides a common API (Application Programming Interface) - for realtime audio input/output across Linux (native ALSA, Jack, - and OSS), Macintosh OS X (CoreAudio and Jack), and Windows - (DirectSound, ASIO and WASAPI) operating systems. - - RtAudio WWW site: http://www.music.mcgill.ca/~gary/rtaudio/ - - RtAudio: realtime audio i/o C++ classes - Copyright (c) 2001-2016 Gary P. Scavone - - Permission is hereby granted, free of charge, to any person - obtaining a copy of this software and associated documentation files - (the "Software"), to deal in the Software without restriction, - including without limitation the rights to use, copy, modify, merge, - publish, distribute, sublicense, and/or sell copies of the Software, - and to permit persons to whom the Software is furnished to do so, - subject to the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - Any person wishing to distribute modifications to the Software is - asked to send the modifications to the original developer so that - they can be incorporated into the canonical version. This is, - however, not a binding provision of this license. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR - ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF - CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ -/************************************************************************/ - -// RtAudio: Version 4.1.2 - -#include "RtAudio.h" -#include <iostream> -#include <cstdlib> -#include <cstring> -#include <climits> -#include <algorithm> - -// Static variable definitions. -const unsigned int RtApi::MAX_SAMPLE_RATES = 14; -const unsigned int RtApi::SAMPLE_RATES[] = { - 4000, 5512, 8000, 9600, 11025, 16000, 22050, - 32000, 44100, 48000, 88200, 96000, 176400, 192000 -}; - -#if defined(__WINDOWS_DS__) || defined(__WINDOWS_ASIO__) || defined(__WINDOWS_WASAPI__) - #define MUTEX_INITIALIZE(A) InitializeCriticalSection(A) - #define MUTEX_DESTROY(A) DeleteCriticalSection(A) - #define MUTEX_LOCK(A) EnterCriticalSection(A) - #define MUTEX_UNLOCK(A) LeaveCriticalSection(A) - - #include "tchar.h" - - static std::string convertCharPointerToStdString(const char *text) - { - return std::string(text); - } - - static std::string convertCharPointerToStdString(const wchar_t *text) - { - int length = WideCharToMultiByte(CP_UTF8, 0, text, -1, NULL, 0, NULL, NULL); - std::string s( length-1, '\0' ); - WideCharToMultiByte(CP_UTF8, 0, text, -1, &s[0], length, NULL, NULL); - return s; - } - -#elif defined(__LINUX_ALSA__) || defined(__LINUX_PULSE__) || defined(__UNIX_JACK__) || defined(__LINUX_OSS__) || defined(__MACOSX_CORE__) - // pthread API - #define MUTEX_INITIALIZE(A) pthread_mutex_init(A, NULL) - #define MUTEX_DESTROY(A) pthread_mutex_destroy(A) - #define MUTEX_LOCK(A) pthread_mutex_lock(A) - #define MUTEX_UNLOCK(A) pthread_mutex_unlock(A) -#else - #define MUTEX_INITIALIZE(A) abs(*A) // dummy definitions - #define MUTEX_DESTROY(A) abs(*A) // dummy definitions -#endif - -// *************************************************** // -// -// RtAudio definitions. -// -// *************************************************** // - -std::string RtAudio :: getVersion( void ) throw() -{ - return RTAUDIO_VERSION; -} - -void RtAudio :: getCompiledApi( std::vector<RtAudio::Api> &apis ) throw() -{ - apis.clear(); - - // The order here will control the order of RtAudio's API search in - // the constructor. -#if defined(__UNIX_JACK__) - apis.push_back( UNIX_JACK ); -#endif -#if defined(__LINUX_ALSA__) - apis.push_back( LINUX_ALSA ); -#endif -#if defined(__LINUX_PULSE__) - apis.push_back( LINUX_PULSE ); -#endif -#if defined(__LINUX_OSS__) - apis.push_back( LINUX_OSS ); -#endif -#if defined(__WINDOWS_ASIO__) - apis.push_back( WINDOWS_ASIO ); -#endif -#if defined(__WINDOWS_WASAPI__) - apis.push_back( WINDOWS_WASAPI ); -#endif -#if defined(__WINDOWS_DS__) - apis.push_back( WINDOWS_DS ); -#endif -#if defined(__MACOSX_CORE__) - apis.push_back( MACOSX_CORE ); -#endif -#if defined(__RTAUDIO_DUMMY__) - apis.push_back( RTAUDIO_DUMMY ); -#endif -} - -void RtAudio :: openRtApi( RtAudio::Api api ) -{ - if ( rtapi_ ) - delete rtapi_; - rtapi_ = 0; - -#if defined(__UNIX_JACK__) - if ( api == UNIX_JACK ) - rtapi_ = new RtApiJack(); -#endif -#if defined(__LINUX_ALSA__) - if ( api == LINUX_ALSA ) - rtapi_ = new RtApiAlsa(); -#endif -#if defined(__LINUX_PULSE__) - if ( api == LINUX_PULSE ) - rtapi_ = new RtApiPulse(); -#endif -#if defined(__LINUX_OSS__) - if ( api == LINUX_OSS ) - rtapi_ = new RtApiOss(); -#endif -#if defined(__WINDOWS_ASIO__) - if ( api == WINDOWS_ASIO ) - rtapi_ = new RtApiAsio(); -#endif -#if defined(__WINDOWS_WASAPI__) - if ( api == WINDOWS_WASAPI ) - rtapi_ = new RtApiWasapi(); -#endif -#if defined(__WINDOWS_DS__) - if ( api == WINDOWS_DS ) - rtapi_ = new RtApiDs(); -#endif -#if defined(__MACOSX_CORE__) - if ( api == MACOSX_CORE ) - rtapi_ = new RtApiCore(); -#endif -#if defined(__RTAUDIO_DUMMY__) - if ( api == RTAUDIO_DUMMY ) - rtapi_ = new RtApiDummy(); -#endif -} - -RtAudio :: RtAudio( RtAudio::Api api ) -{ - rtapi_ = 0; - - if ( api != UNSPECIFIED ) { - // Attempt to open the specified API. - openRtApi( api ); - if ( rtapi_ ) return; - - // No compiled support for specified API value. Issue a debug - // warning and continue as if no API was specified. - std::cerr << "\nRtAudio: no compiled support for specified API argument!\n" << std::endl; - } - - // Iterate through the compiled APIs and return as soon as we find - // one with at least one device or we reach the end of the list. - std::vector< RtAudio::Api > apis; - getCompiledApi( apis ); - for ( unsigned int i=0; i<apis.size(); i++ ) { - openRtApi( apis[i] ); - if ( rtapi_ && rtapi_->getDeviceCount() ) break; - } - - if ( rtapi_ ) return; - - // It should not be possible to get here because the preprocessor - // definition __RTAUDIO_DUMMY__ is automatically defined if no - // API-specific definitions are passed to the compiler. But just in - // case something weird happens, we'll thow an error. - std::string errorText = "\nRtAudio: no compiled API support found ... critical error!!\n\n"; - throw( RtAudioError( errorText, RtAudioError::UNSPECIFIED ) ); -} - -RtAudio :: ~RtAudio() throw() -{ - if ( rtapi_ ) - delete rtapi_; -} - -void RtAudio :: openStream( RtAudio::StreamParameters *outputParameters, - RtAudio::StreamParameters *inputParameters, - RtAudioFormat format, unsigned int sampleRate, - unsigned int *bufferFrames, - RtAudioCallback callback, void *userData, - RtAudio::StreamOptions *options, - RtAudioErrorCallback errorCallback ) -{ - return rtapi_->openStream( outputParameters, inputParameters, format, - sampleRate, bufferFrames, callback, - userData, options, errorCallback ); -} - -// *************************************************** // -// -// Public RtApi definitions (see end of file for -// private or protected utility functions). -// -// *************************************************** // - -RtApi :: RtApi() -{ - stream_.state = STREAM_CLOSED; - stream_.mode = UNINITIALIZED; - stream_.apiHandle = 0; - stream_.userBuffer[0] = 0; - stream_.userBuffer[1] = 0; - MUTEX_INITIALIZE( &stream_.mutex ); - showWarnings_ = true; - firstErrorOccurred_ = false; -} - -RtApi :: ~RtApi() -{ - MUTEX_DESTROY( &stream_.mutex ); -} - -void RtApi :: openStream( RtAudio::StreamParameters *oParams, - RtAudio::StreamParameters *iParams, - RtAudioFormat format, unsigned int sampleRate, - unsigned int *bufferFrames, - RtAudioCallback callback, void *userData, - RtAudio::StreamOptions *options, - RtAudioErrorCallback errorCallback ) -{ - if ( stream_.state != STREAM_CLOSED ) { - errorText_ = "RtApi::openStream: a stream is already open!"; - error( RtAudioError::INVALID_USE ); - return; - } - - // Clear stream information potentially left from a previously open stream. - clearStreamInfo(); - - if ( oParams && oParams->nChannels < 1 ) { - errorText_ = "RtApi::openStream: a non-NULL output StreamParameters structure cannot have an nChannels value less than one."; - error( RtAudioError::INVALID_USE ); - return; - } - - if ( iParams && iParams->nChannels < 1 ) { - errorText_ = "RtApi::openStream: a non-NULL input StreamParameters structure cannot have an nChannels value less than one."; - error( RtAudioError::INVALID_USE ); - return; - } - - if ( oParams == NULL && iParams == NULL ) { - errorText_ = "RtApi::openStream: input and output StreamParameters structures are both NULL!"; - error( RtAudioError::INVALID_USE ); - return; - } - - if ( formatBytes(format) == 0 ) { - errorText_ = "RtApi::openStream: 'format' parameter value is undefined."; - error( RtAudioError::INVALID_USE ); - return; - } - - unsigned int nDevices = getDeviceCount(); - unsigned int oChannels = 0; - if ( oParams ) { - oChannels = oParams->nChannels; - if ( oParams->deviceId >= nDevices ) { - errorText_ = "RtApi::openStream: output device parameter value is invalid."; - error( RtAudioError::INVALID_USE ); - return; - } - } - - unsigned int iChannels = 0; - if ( iParams ) { - iChannels = iParams->nChannels; - if ( iParams->deviceId >= nDevices ) { - errorText_ = "RtApi::openStream: input device parameter value is invalid."; - error( RtAudioError::INVALID_USE ); - return; - } - } - - bool result; - - if ( oChannels > 0 ) { - - result = probeDeviceOpen( oParams->deviceId, OUTPUT, oChannels, oParams->firstChannel, - sampleRate, format, bufferFrames, options ); - if ( result == false ) { - error( RtAudioError::SYSTEM_ERROR ); - return; - } - } - - if ( iChannels > 0 ) { - - result = probeDeviceOpen( iParams->deviceId, INPUT, iChannels, iParams->firstChannel, - sampleRate, format, bufferFrames, options ); - if ( result == false ) { - if ( oChannels > 0 ) closeStream(); - error( RtAudioError::SYSTEM_ERROR ); - return; - } - } - - stream_.callbackInfo.callback = (void *) callback; - stream_.callbackInfo.userData = userData; - stream_.callbackInfo.errorCallback = (void *) errorCallback; - - if ( options ) options->numberOfBuffers = stream_.nBuffers; - stream_.state = STREAM_STOPPED; -} - -unsigned int RtApi :: getDefaultInputDevice( void ) -{ - // Should be implemented in subclasses if possible. - return 0; -} - -unsigned int RtApi :: getDefaultOutputDevice( void ) -{ - // Should be implemented in subclasses if possible. - return 0; -} - -void RtApi :: closeStream( void ) -{ - // MUST be implemented in subclasses! - return; -} - -bool RtApi :: probeDeviceOpen( unsigned int /*device*/, StreamMode /*mode*/, unsigned int /*channels*/, - unsigned int /*firstChannel*/, unsigned int /*sampleRate*/, - RtAudioFormat /*format*/, unsigned int * /*bufferSize*/, - RtAudio::StreamOptions * /*options*/ ) -{ - // MUST be implemented in subclasses! - return FAILURE; -} - -void RtApi :: tickStreamTime( void ) -{ - // Subclasses that do not provide their own implementation of - // getStreamTime should call this function once per buffer I/O to - // provide basic stream time support. - - stream_.streamTime += ( stream_.bufferSize * 1.0 / stream_.sampleRate ); - -#if defined( HAVE_GETTIMEOFDAY ) - gettimeofday( &stream_.lastTickTimestamp, NULL ); -#endif -} - -long RtApi :: getStreamLatency( void ) -{ - verifyStream(); - - long totalLatency = 0; - if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) - totalLatency = stream_.latency[0]; - if ( stream_.mode == INPUT || stream_.mode == DUPLEX ) - totalLatency += stream_.latency[1]; - - return totalLatency; -} - -double RtApi :: getStreamTime( void ) -{ - verifyStream(); - -#if defined( HAVE_GETTIMEOFDAY ) - // Return a very accurate estimate of the stream time by - // adding in the elapsed time since the last tick. - struct timeval then; - struct timeval now; - - if ( stream_.state != STREAM_RUNNING || stream_.streamTime == 0.0 ) - return stream_.streamTime; - - gettimeofday( &now, NULL ); - then = stream_.lastTickTimestamp; - return stream_.streamTime + - ((now.tv_sec + 0.000001 * now.tv_usec) - - (then.tv_sec + 0.000001 * then.tv_usec)); -#else - return stream_.streamTime; -#endif -} - -void RtApi :: setStreamTime( double time ) -{ - verifyStream(); - - if ( time >= 0.0 ) - stream_.streamTime = time; -} - -unsigned int RtApi :: getStreamSampleRate( void ) -{ - verifyStream(); - - return stream_.sampleRate; -} - - -// *************************************************** // -// -// OS/API-specific methods. -// -// *************************************************** // - -#if defined(__MACOSX_CORE__) - -// The OS X CoreAudio API is designed to use a separate callback -// procedure for each of its audio devices. A single RtAudio duplex -// stream using two different devices is supported here, though it -// cannot be guaranteed to always behave correctly because we cannot -// synchronize these two callbacks. -// -// A property listener is installed for over/underrun information. -// However, no functionality is currently provided to allow property -// listeners to trigger user handlers because it is unclear what could -// be done if a critical stream parameter (buffer size, sample rate, -// device disconnect) notification arrived. The listeners entail -// quite a bit of extra code and most likely, a user program wouldn't -// be prepared for the result anyway. However, we do provide a flag -// to the client callback function to inform of an over/underrun. - -// A structure to hold various information related to the CoreAudio API -// implementation. -struct CoreHandle { - AudioDeviceID id[2]; // device ids -#if defined( MAC_OS_X_VERSION_10_5 ) && ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 ) - AudioDeviceIOProcID procId[2]; -#endif - UInt32 iStream[2]; // device stream index (or first if using multiple) - UInt32 nStreams[2]; // number of streams to use - bool xrun[2]; - char *deviceBuffer; - pthread_cond_t condition; - int drainCounter; // Tracks callback counts when draining - bool internalDrain; // Indicates if stop is initiated from callback or not. - - CoreHandle() - :deviceBuffer(0), drainCounter(0), internalDrain(false) { nStreams[0] = 1; nStreams[1] = 1; id[0] = 0; id[1] = 0; xrun[0] = false; xrun[1] = false; } -}; - -RtApiCore:: RtApiCore() -{ -#if defined( AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER ) - // This is a largely undocumented but absolutely necessary - // requirement starting with OS-X 10.6. If not called, queries and - // updates to various audio device properties are not handled - // correctly. - CFRunLoopRef theRunLoop = NULL; - AudioObjectPropertyAddress property = { kAudioHardwarePropertyRunLoop, - kAudioObjectPropertyScopeGlobal, - kAudioObjectPropertyElementMaster }; - OSStatus result = AudioObjectSetPropertyData( kAudioObjectSystemObject, &property, 0, NULL, sizeof(CFRunLoopRef), &theRunLoop); - if ( result != noErr ) { - errorText_ = "RtApiCore::RtApiCore: error setting run loop property!"; - error( RtAudioError::WARNING ); - } -#endif -} - -RtApiCore :: ~RtApiCore() -{ - // The subclass destructor gets called before the base class - // destructor, so close an existing stream before deallocating - // apiDeviceId memory. - if ( stream_.state != STREAM_CLOSED ) closeStream(); -} - -unsigned int RtApiCore :: getDeviceCount( void ) -{ - // Find out how many audio devices there are, if any. - UInt32 dataSize; - AudioObjectPropertyAddress propertyAddress = { kAudioHardwarePropertyDevices, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster }; - OSStatus result = AudioObjectGetPropertyDataSize( kAudioObjectSystemObject, &propertyAddress, 0, NULL, &dataSize ); - if ( result != noErr ) { - errorText_ = "RtApiCore::getDeviceCount: OS-X error getting device info!"; - error( RtAudioError::WARNING ); - return 0; - } - - return dataSize / sizeof( AudioDeviceID ); -} - -unsigned int RtApiCore :: getDefaultInputDevice( void ) -{ - unsigned int nDevices = getDeviceCount(); - if ( nDevices <= 1 ) return 0; - - AudioDeviceID id; - UInt32 dataSize = sizeof( AudioDeviceID ); - AudioObjectPropertyAddress property = { kAudioHardwarePropertyDefaultInputDevice, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster }; - OSStatus result = AudioObjectGetPropertyData( kAudioObjectSystemObject, &property, 0, NULL, &dataSize, &id ); - if ( result != noErr ) { - errorText_ = "RtApiCore::getDefaultInputDevice: OS-X system error getting device."; - error( RtAudioError::WARNING ); - return 0; - } - - dataSize *= nDevices; - AudioDeviceID deviceList[ nDevices ]; - property.mSelector = kAudioHardwarePropertyDevices; - result = AudioObjectGetPropertyData( kAudioObjectSystemObject, &property, 0, NULL, &dataSize, (void *) &deviceList ); - if ( result != noErr ) { - errorText_ = "RtApiCore::getDefaultInputDevice: OS-X system error getting device IDs."; - error( RtAudioError::WARNING ); - return 0; - } - - for ( unsigned int i=0; i<nDevices; i++ ) - if ( id == deviceList[i] ) return i; - - errorText_ = "RtApiCore::getDefaultInputDevice: No default device found!"; - error( RtAudioError::WARNING ); - return 0; -} - -unsigned int RtApiCore :: getDefaultOutputDevice( void ) -{ - unsigned int nDevices = getDeviceCount(); - if ( nDevices <= 1 ) return 0; - - AudioDeviceID id; - UInt32 dataSize = sizeof( AudioDeviceID ); - AudioObjectPropertyAddress property = { kAudioHardwarePropertyDefaultOutputDevice, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster }; - OSStatus result = AudioObjectGetPropertyData( kAudioObjectSystemObject, &property, 0, NULL, &dataSize, &id ); - if ( result != noErr ) { - errorText_ = "RtApiCore::getDefaultOutputDevice: OS-X system error getting device."; - error( RtAudioError::WARNING ); - return 0; - } - - dataSize = sizeof( AudioDeviceID ) * nDevices; - AudioDeviceID deviceList[ nDevices ]; - property.mSelector = kAudioHardwarePropertyDevices; - result = AudioObjectGetPropertyData( kAudioObjectSystemObject, &property, 0, NULL, &dataSize, (void *) &deviceList ); - if ( result != noErr ) { - errorText_ = "RtApiCore::getDefaultOutputDevice: OS-X system error getting device IDs."; - error( RtAudioError::WARNING ); - return 0; - } - - for ( unsigned int i=0; i<nDevices; i++ ) - if ( id == deviceList[i] ) return i; - - errorText_ = "RtApiCore::getDefaultOutputDevice: No default device found!"; - error( RtAudioError::WARNING ); - return 0; -} - -RtAudio::DeviceInfo RtApiCore :: getDeviceInfo( unsigned int device ) -{ - RtAudio::DeviceInfo info; - info.probed = false; - - // Get device ID - unsigned int nDevices = getDeviceCount(); - if ( nDevices == 0 ) { - errorText_ = "RtApiCore::getDeviceInfo: no devices found!"; - error( RtAudioError::INVALID_USE ); - return info; - } - - if ( device >= nDevices ) { - errorText_ = "RtApiCore::getDeviceInfo: device ID is invalid!"; - error( RtAudioError::INVALID_USE ); - return info; - } - - AudioDeviceID deviceList[ nDevices ]; - UInt32 dataSize = sizeof( AudioDeviceID ) * nDevices; - AudioObjectPropertyAddress property = { kAudioHardwarePropertyDevices, - kAudioObjectPropertyScopeGlobal, - kAudioObjectPropertyElementMaster }; - OSStatus result = AudioObjectGetPropertyData( kAudioObjectSystemObject, &property, - 0, NULL, &dataSize, (void *) &deviceList ); - if ( result != noErr ) { - errorText_ = "RtApiCore::getDeviceInfo: OS-X system error getting device IDs."; - error( RtAudioError::WARNING ); - return info; - } - - AudioDeviceID id = deviceList[ device ]; - - // Get the device name. - info.name.erase(); - CFStringRef cfname; - dataSize = sizeof( CFStringRef ); - property.mSelector = kAudioObjectPropertyManufacturer; - result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, &cfname ); - if ( result != noErr ) { - errorStream_ << "RtApiCore::probeDeviceInfo: system error (" << getErrorCode( result ) << ") getting device manufacturer."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - return info; - } - - //const char *mname = CFStringGetCStringPtr( cfname, CFStringGetSystemEncoding() ); - int length = CFStringGetLength(cfname); - char *mname = (char *)malloc(length * 3 + 1); -#if defined( UNICODE ) || defined( _UNICODE ) - CFStringGetCString(cfname, mname, length * 3 + 1, kCFStringEncodingUTF8); -#else - CFStringGetCString(cfname, mname, length * 3 + 1, CFStringGetSystemEncoding()); -#endif - info.name.append( (const char *)mname, strlen(mname) ); - info.name.append( ": " ); - CFRelease( cfname ); - free(mname); - - property.mSelector = kAudioObjectPropertyName; - result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, &cfname ); - if ( result != noErr ) { - errorStream_ << "RtApiCore::probeDeviceInfo: system error (" << getErrorCode( result ) << ") getting device name."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - return info; - } - - //const char *name = CFStringGetCStringPtr( cfname, CFStringGetSystemEncoding() ); - length = CFStringGetLength(cfname); - char *name = (char *)malloc(length * 3 + 1); -#if defined( UNICODE ) || defined( _UNICODE ) - CFStringGetCString(cfname, name, length * 3 + 1, kCFStringEncodingUTF8); -#else - CFStringGetCString(cfname, name, length * 3 + 1, CFStringGetSystemEncoding()); -#endif - info.name.append( (const char *)name, strlen(name) ); - CFRelease( cfname ); - free(name); - - // Get the output stream "configuration". - AudioBufferList *bufferList = nil; - property.mSelector = kAudioDevicePropertyStreamConfiguration; - property.mScope = kAudioDevicePropertyScopeOutput; - // property.mElement = kAudioObjectPropertyElementWildcard; - dataSize = 0; - result = AudioObjectGetPropertyDataSize( id, &property, 0, NULL, &dataSize ); - if ( result != noErr || dataSize == 0 ) { - errorStream_ << "RtApiCore::getDeviceInfo: system error (" << getErrorCode( result ) << ") getting output stream configuration info for device (" << device << ")."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - return info; - } - - // Allocate the AudioBufferList. - bufferList = (AudioBufferList *) malloc( dataSize ); - if ( bufferList == NULL ) { - errorText_ = "RtApiCore::getDeviceInfo: memory error allocating output AudioBufferList."; - error( RtAudioError::WARNING ); - return info; - } - - result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, bufferList ); - if ( result != noErr || dataSize == 0 ) { - free( bufferList ); - errorStream_ << "RtApiCore::getDeviceInfo: system error (" << getErrorCode( result ) << ") getting output stream configuration for device (" << device << ")."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - return info; - } - - // Get output channel information. - unsigned int i, nStreams = bufferList->mNumberBuffers; - for ( i=0; i<nStreams; i++ ) - info.outputChannels += bufferList->mBuffers[i].mNumberChannels; - free( bufferList ); - - // Get the input stream "configuration". - property.mScope = kAudioDevicePropertyScopeInput; - result = AudioObjectGetPropertyDataSize( id, &property, 0, NULL, &dataSize ); - if ( result != noErr || dataSize == 0 ) { - errorStream_ << "RtApiCore::getDeviceInfo: system error (" << getErrorCode( result ) << ") getting input stream configuration info for device (" << device << ")."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - return info; - } - - // Allocate the AudioBufferList. - bufferList = (AudioBufferList *) malloc( dataSize ); - if ( bufferList == NULL ) { - errorText_ = "RtApiCore::getDeviceInfo: memory error allocating input AudioBufferList."; - error( RtAudioError::WARNING ); - return info; - } - - result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, bufferList ); - if (result != noErr || dataSize == 0) { - free( bufferList ); - errorStream_ << "RtApiCore::getDeviceInfo: system error (" << getErrorCode( result ) << ") getting input stream configuration for device (" << device << ")."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - return info; - } - - // Get input channel information. - nStreams = bufferList->mNumberBuffers; - for ( i=0; i<nStreams; i++ ) - info.inputChannels += bufferList->mBuffers[i].mNumberChannels; - free( bufferList ); - - // If device opens for both playback and capture, we determine the channels. - if ( info.outputChannels > 0 && info.inputChannels > 0 ) - info.duplexChannels = (info.outputChannels > info.inputChannels) ? info.inputChannels : info.outputChannels; - - // Probe the device sample rates. - bool isInput = false; - if ( info.outputChannels == 0 ) isInput = true; - - // Determine the supported sample rates. - property.mSelector = kAudioDevicePropertyAvailableNominalSampleRates; - if ( isInput == false ) property.mScope = kAudioDevicePropertyScopeOutput; - result = AudioObjectGetPropertyDataSize( id, &property, 0, NULL, &dataSize ); - if ( result != kAudioHardwareNoError || dataSize == 0 ) { - errorStream_ << "RtApiCore::getDeviceInfo: system error (" << getErrorCode( result ) << ") getting sample rate info."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - return info; - } - - UInt32 nRanges = dataSize / sizeof( AudioValueRange ); - AudioValueRange rangeList[ nRanges ]; - result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, &rangeList ); - if ( result != kAudioHardwareNoError ) { - errorStream_ << "RtApiCore::getDeviceInfo: system error (" << getErrorCode( result ) << ") getting sample rates."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - return info; - } - - // The sample rate reporting mechanism is a bit of a mystery. It - // seems that it can either return individual rates or a range of - // rates. I assume that if the min / max range values are the same, - // then that represents a single supported rate and if the min / max - // range values are different, the device supports an arbitrary - // range of values (though there might be multiple ranges, so we'll - // use the most conservative range). - Float64 minimumRate = 1.0, maximumRate = 10000000000.0; - bool haveValueRange = false; - info.sampleRates.clear(); - for ( UInt32 i=0; i<nRanges; i++ ) { - if ( rangeList[i].mMinimum == rangeList[i].mMaximum ) { - unsigned int tmpSr = (unsigned int) rangeList[i].mMinimum; - info.sampleRates.push_back( tmpSr ); - - if ( !info.preferredSampleRate || ( tmpSr <= 48000 && tmpSr > info.preferredSampleRate ) ) - info.preferredSampleRate = tmpSr; - - } else { - haveValueRange = true; - if ( rangeList[i].mMinimum > minimumRate ) minimumRate = rangeList[i].mMinimum; - if ( rangeList[i].mMaximum < maximumRate ) maximumRate = rangeList[i].mMaximum; - } - } - - if ( haveValueRange ) { - for ( unsigned int k=0; k<MAX_SAMPLE_RATES; k++ ) { - if ( SAMPLE_RATES[k] >= (unsigned int) minimumRate && SAMPLE_RATES[k] <= (unsigned int) maximumRate ) { - info.sampleRates.push_back( SAMPLE_RATES[k] ); - - if ( !info.preferredSampleRate || ( SAMPLE_RATES[k] <= 48000 && SAMPLE_RATES[k] > info.preferredSampleRate ) ) - info.preferredSampleRate = SAMPLE_RATES[k]; - } - } - } - - // Sort and remove any redundant values - std::sort( info.sampleRates.begin(), info.sampleRates.end() ); - info.sampleRates.erase( unique( info.sampleRates.begin(), info.sampleRates.end() ), info.sampleRates.end() ); - - if ( info.sampleRates.size() == 0 ) { - errorStream_ << "RtApiCore::probeDeviceInfo: No supported sample rates found for device (" << device << ")."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - return info; - } - - // CoreAudio always uses 32-bit floating point data for PCM streams. - // Thus, any other "physical" formats supported by the device are of - // no interest to the client. - info.nativeFormats = RTAUDIO_FLOAT32; - - if ( info.outputChannels > 0 ) - if ( getDefaultOutputDevice() == device ) info.isDefaultOutput = true; - if ( info.inputChannels > 0 ) - if ( getDefaultInputDevice() == device ) info.isDefaultInput = true; - - info.probed = true; - return info; -} - -static OSStatus callbackHandler( AudioDeviceID inDevice, - const AudioTimeStamp* /*inNow*/, - const AudioBufferList* inInputData, - const AudioTimeStamp* /*inInputTime*/, - AudioBufferList* outOutputData, - const AudioTimeStamp* /*inOutputTime*/, - void* infoPointer ) -{ - CallbackInfo *info = (CallbackInfo *) infoPointer; - - RtApiCore *object = (RtApiCore *) info->object; - if ( object->callbackEvent( inDevice, inInputData, outOutputData ) == false ) - return kAudioHardwareUnspecifiedError; - else - return kAudioHardwareNoError; -} - -static OSStatus xrunListener( AudioObjectID /*inDevice*/, - UInt32 nAddresses, - const AudioObjectPropertyAddress properties[], - void* handlePointer ) -{ - CoreHandle *handle = (CoreHandle *) handlePointer; - for ( UInt32 i=0; i<nAddresses; i++ ) { - if ( properties[i].mSelector == kAudioDeviceProcessorOverload ) { - if ( properties[i].mScope == kAudioDevicePropertyScopeInput ) - handle->xrun[1] = true; - else - handle->xrun[0] = true; - } - } - - return kAudioHardwareNoError; -} - -static OSStatus rateListener( AudioObjectID inDevice, - UInt32 /*nAddresses*/, - const AudioObjectPropertyAddress /*properties*/[], - void* ratePointer ) -{ - Float64 *rate = (Float64 *) ratePointer; - UInt32 dataSize = sizeof( Float64 ); - AudioObjectPropertyAddress property = { kAudioDevicePropertyNominalSampleRate, - kAudioObjectPropertyScopeGlobal, - kAudioObjectPropertyElementMaster }; - AudioObjectGetPropertyData( inDevice, &property, 0, NULL, &dataSize, rate ); - return kAudioHardwareNoError; -} - -bool RtApiCore :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, - unsigned int firstChannel, unsigned int sampleRate, - RtAudioFormat format, unsigned int *bufferSize, - RtAudio::StreamOptions *options ) -{ - // Get device ID - unsigned int nDevices = getDeviceCount(); - if ( nDevices == 0 ) { - // This should not happen because a check is made before this function is called. - errorText_ = "RtApiCore::probeDeviceOpen: no devices found!"; - return FAILURE; - } - - if ( device >= nDevices ) { - // This should not happen because a check is made before this function is called. - errorText_ = "RtApiCore::probeDeviceOpen: device ID is invalid!"; - return FAILURE; - } - - AudioDeviceID deviceList[ nDevices ]; - UInt32 dataSize = sizeof( AudioDeviceID ) * nDevices; - AudioObjectPropertyAddress property = { kAudioHardwarePropertyDevices, - kAudioObjectPropertyScopeGlobal, - kAudioObjectPropertyElementMaster }; - OSStatus result = AudioObjectGetPropertyData( kAudioObjectSystemObject, &property, - 0, NULL, &dataSize, (void *) &deviceList ); - if ( result != noErr ) { - errorText_ = "RtApiCore::probeDeviceOpen: OS-X system error getting device IDs."; - return FAILURE; - } - - AudioDeviceID id = deviceList[ device ]; - - // Setup for stream mode. - bool isInput = false; - if ( mode == INPUT ) { - isInput = true; - property.mScope = kAudioDevicePropertyScopeInput; - } - else - property.mScope = kAudioDevicePropertyScopeOutput; - - // Get the stream "configuration". - AudioBufferList *bufferList = nil; - dataSize = 0; - property.mSelector = kAudioDevicePropertyStreamConfiguration; - result = AudioObjectGetPropertyDataSize( id, &property, 0, NULL, &dataSize ); - if ( result != noErr || dataSize == 0 ) { - errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") getting stream configuration info for device (" << device << ")."; - errorText_ = errorStream_.str(); - return FAILURE; - } - - // Allocate the AudioBufferList. - bufferList = (AudioBufferList *) malloc( dataSize ); - if ( bufferList == NULL ) { - errorText_ = "RtApiCore::probeDeviceOpen: memory error allocating AudioBufferList."; - return FAILURE; - } - - result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, bufferList ); - if (result != noErr || dataSize == 0) { - free( bufferList ); - errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") getting stream configuration for device (" << device << ")."; - errorText_ = errorStream_.str(); - return FAILURE; - } - - // Search for one or more streams that contain the desired number of - // channels. CoreAudio devices can have an arbitrary number of - // streams and each stream can have an arbitrary number of channels. - // For each stream, a single buffer of interleaved samples is - // provided. RtAudio prefers the use of one stream of interleaved - // data or multiple consecutive single-channel streams. However, we - // now support multiple consecutive multi-channel streams of - // interleaved data as well. - UInt32 iStream, offsetCounter = firstChannel; - UInt32 nStreams = bufferList->mNumberBuffers; - bool monoMode = false; - bool foundStream = false; - - // First check that the device supports the requested number of - // channels. - UInt32 deviceChannels = 0; - for ( iStream=0; iStream<nStreams; iStream++ ) - deviceChannels += bufferList->mBuffers[iStream].mNumberChannels; - - if ( deviceChannels < ( channels + firstChannel ) ) { - free( bufferList ); - errorStream_ << "RtApiCore::probeDeviceOpen: the device (" << device << ") does not support the requested channel count."; - errorText_ = errorStream_.str(); - return FAILURE; - } - - // Look for a single stream meeting our needs. - UInt32 firstStream, streamCount = 1, streamChannels = 0, channelOffset = 0; - for ( iStream=0; iStream<nStreams; iStream++ ) { - streamChannels = bufferList->mBuffers[iStream].mNumberChannels; - if ( streamChannels >= channels + offsetCounter ) { - firstStream = iStream; - channelOffset = offsetCounter; - foundStream = true; - break; - } - if ( streamChannels > offsetCounter ) break; - offsetCounter -= streamChannels; - } - - // If we didn't find a single stream above, then we should be able - // to meet the channel specification with multiple streams. - if ( foundStream == false ) { - monoMode = true; - offsetCounter = firstChannel; - for ( iStream=0; iStream<nStreams; iStream++ ) { - streamChannels = bufferList->mBuffers[iStream].mNumberChannels; - if ( streamChannels > offsetCounter ) break; - offsetCounter -= streamChannels; - } - - firstStream = iStream; - channelOffset = offsetCounter; - Int32 channelCounter = channels + offsetCounter - streamChannels; - - if ( streamChannels > 1 ) monoMode = false; - while ( channelCounter > 0 ) { - streamChannels = bufferList->mBuffers[++iStream].mNumberChannels; - if ( streamChannels > 1 ) monoMode = false; - channelCounter -= streamChannels; - streamCount++; - } - } - - free( bufferList ); - - // Determine the buffer size. - AudioValueRange bufferRange; - dataSize = sizeof( AudioValueRange ); - property.mSelector = kAudioDevicePropertyBufferFrameSizeRange; - result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, &bufferRange ); - - if ( result != noErr ) { - errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") getting buffer size range for device (" << device << ")."; - errorText_ = errorStream_.str(); - return FAILURE; - } - - if ( bufferRange.mMinimum > *bufferSize ) *bufferSize = (unsigned long) bufferRange.mMinimum; - else if ( bufferRange.mMaximum < *bufferSize ) *bufferSize = (unsigned long) bufferRange.mMaximum; - if ( options && options->flags & RTAUDIO_MINIMIZE_LATENCY ) *bufferSize = (unsigned long) bufferRange.mMinimum; - - // Set the buffer size. For multiple streams, I'm assuming we only - // need to make this setting for the master channel. - UInt32 theSize = (UInt32) *bufferSize; - dataSize = sizeof( UInt32 ); - property.mSelector = kAudioDevicePropertyBufferFrameSize; - result = AudioObjectSetPropertyData( id, &property, 0, NULL, dataSize, &theSize ); - - if ( result != noErr ) { - errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") setting the buffer size for device (" << device << ")."; - errorText_ = errorStream_.str(); - return FAILURE; - } - - // If attempting to setup a duplex stream, the bufferSize parameter - // MUST be the same in both directions! - *bufferSize = theSize; - if ( stream_.mode == OUTPUT && mode == INPUT && *bufferSize != stream_.bufferSize ) { - errorStream_ << "RtApiCore::probeDeviceOpen: system error setting buffer size for duplex stream on device (" << device << ")."; - errorText_ = errorStream_.str(); - return FAILURE; - } - - stream_.bufferSize = *bufferSize; - stream_.nBuffers = 1; - - // Try to set "hog" mode ... it's not clear to me this is working. - if ( options && options->flags & RTAUDIO_HOG_DEVICE ) { - pid_t hog_pid; - dataSize = sizeof( hog_pid ); - property.mSelector = kAudioDevicePropertyHogMode; - result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, &hog_pid ); - if ( result != noErr ) { - errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") getting 'hog' state!"; - errorText_ = errorStream_.str(); - return FAILURE; - } - - if ( hog_pid != getpid() ) { - hog_pid = getpid(); - result = AudioObjectSetPropertyData( id, &property, 0, NULL, dataSize, &hog_pid ); - if ( result != noErr ) { - errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") setting 'hog' state!"; - errorText_ = errorStream_.str(); - return FAILURE; - } - } - } - - // Check and if necessary, change the sample rate for the device. - Float64 nominalRate; - dataSize = sizeof( Float64 ); - property.mSelector = kAudioDevicePropertyNominalSampleRate; - result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, &nominalRate ); - if ( result != noErr ) { - errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") getting current sample rate."; - errorText_ = errorStream_.str(); - return FAILURE; - } - - // Only change the sample rate if off by more than 1 Hz. - if ( fabs( nominalRate - (double)sampleRate ) > 1.0 ) { - - // Set a property listener for the sample rate change - Float64 reportedRate = 0.0; - AudioObjectPropertyAddress tmp = { kAudioDevicePropertyNominalSampleRate, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster }; - result = AudioObjectAddPropertyListener( id, &tmp, rateListener, (void *) &reportedRate ); - if ( result != noErr ) { - errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") setting sample rate property listener for device (" << device << ")."; - errorText_ = errorStream_.str(); - return FAILURE; - } - - nominalRate = (Float64) sampleRate; - result = AudioObjectSetPropertyData( id, &property, 0, NULL, dataSize, &nominalRate ); - if ( result != noErr ) { - AudioObjectRemovePropertyListener( id, &tmp, rateListener, (void *) &reportedRate ); - errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") setting sample rate for device (" << device << ")."; - errorText_ = errorStream_.str(); - return FAILURE; - } - - // Now wait until the reported nominal rate is what we just set. - UInt32 microCounter = 0; - while ( reportedRate != nominalRate ) { - microCounter += 5000; - if ( microCounter > 5000000 ) break; - usleep( 5000 ); - } - - // Remove the property listener. - AudioObjectRemovePropertyListener( id, &tmp, rateListener, (void *) &reportedRate ); - - if ( microCounter > 5000000 ) { - errorStream_ << "RtApiCore::probeDeviceOpen: timeout waiting for sample rate update for device (" << device << ")."; - errorText_ = errorStream_.str(); - return FAILURE; - } - } - - // Now set the stream format for all streams. Also, check the - // physical format of the device and change that if necessary. - AudioStreamBasicDescription description; - dataSize = sizeof( AudioStreamBasicDescription ); - property.mSelector = kAudioStreamPropertyVirtualFormat; - result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, &description ); - if ( result != noErr ) { - errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") getting stream format for device (" << device << ")."; - errorText_ = errorStream_.str(); - return FAILURE; - } - - // Set the sample rate and data format id. However, only make the - // change if the sample rate is not within 1.0 of the desired - // rate and the format is not linear pcm. - bool updateFormat = false; - if ( fabs( description.mSampleRate - (Float64)sampleRate ) > 1.0 ) { - description.mSampleRate = (Float64) sampleRate; - updateFormat = true; - } - - if ( description.mFormatID != kAudioFormatLinearPCM ) { - description.mFormatID = kAudioFormatLinearPCM; - updateFormat = true; - } - - if ( updateFormat ) { - result = AudioObjectSetPropertyData( id, &property, 0, NULL, dataSize, &description ); - if ( result != noErr ) { - errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") setting sample rate or data format for device (" << device << ")."; - errorText_ = errorStream_.str(); - return FAILURE; - } - } - - // Now check the physical format. - property.mSelector = kAudioStreamPropertyPhysicalFormat; - result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, &description ); - if ( result != noErr ) { - errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") getting stream physical format for device (" << device << ")."; - errorText_ = errorStream_.str(); - return FAILURE; - } - - //std::cout << "Current physical stream format:" << std::endl; - //std::cout << " mBitsPerChan = " << description.mBitsPerChannel << std::endl; - //std::cout << " aligned high = " << (description.mFormatFlags & kAudioFormatFlagIsAlignedHigh) << ", isPacked = " << (description.mFormatFlags & kAudioFormatFlagIsPacked) << std::endl; - //std::cout << " bytesPerFrame = " << description.mBytesPerFrame << std::endl; - //std::cout << " sample rate = " << description.mSampleRate << std::endl; - - if ( description.mFormatID != kAudioFormatLinearPCM || description.mBitsPerChannel < 16 ) { - description.mFormatID = kAudioFormatLinearPCM; - //description.mSampleRate = (Float64) sampleRate; - AudioStreamBasicDescription testDescription = description; - UInt32 formatFlags; - - // We'll try higher bit rates first and then work our way down. - std::vector< std::pair<UInt32, UInt32> > physicalFormats; - formatFlags = (description.mFormatFlags | kLinearPCMFormatFlagIsFloat) & ~kLinearPCMFormatFlagIsSignedInteger; - physicalFormats.push_back( std::pair<Float32, UInt32>( 32, formatFlags ) ); - formatFlags = (description.mFormatFlags | kLinearPCMFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked) & ~kLinearPCMFormatFlagIsFloat; - physicalFormats.push_back( std::pair<Float32, UInt32>( 32, formatFlags ) ); - physicalFormats.push_back( std::pair<Float32, UInt32>( 24, formatFlags ) ); // 24-bit packed - formatFlags &= ~( kAudioFormatFlagIsPacked | kAudioFormatFlagIsAlignedHigh ); - physicalFormats.push_back( std::pair<Float32, UInt32>( 24.2, formatFlags ) ); // 24-bit in 4 bytes, aligned low - formatFlags |= kAudioFormatFlagIsAlignedHigh; - physicalFormats.push_back( std::pair<Float32, UInt32>( 24.4, formatFlags ) ); // 24-bit in 4 bytes, aligned high - formatFlags = (description.mFormatFlags | kLinearPCMFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked) & ~kLinearPCMFormatFlagIsFloat; - physicalFormats.push_back( std::pair<Float32, UInt32>( 16, formatFlags ) ); - physicalFormats.push_back( std::pair<Float32, UInt32>( 8, formatFlags ) ); - - bool setPhysicalFormat = false; - for( unsigned int i=0; i<physicalFormats.size(); i++ ) { - testDescription = description; - testDescription.mBitsPerChannel = (UInt32) physicalFormats[i].first; - testDescription.mFormatFlags = physicalFormats[i].second; - if ( (24 == (UInt32)physicalFormats[i].first) && ~( physicalFormats[i].second & kAudioFormatFlagIsPacked ) ) - testDescription.mBytesPerFrame = 4 * testDescription.mChannelsPerFrame; - else - testDescription.mBytesPerFrame = testDescription.mBitsPerChannel/8 * testDescription.mChannelsPerFrame; - testDescription.mBytesPerPacket = testDescription.mBytesPerFrame * testDescription.mFramesPerPacket; - result = AudioObjectSetPropertyData( id, &property, 0, NULL, dataSize, &testDescription ); - if ( result == noErr ) { - setPhysicalFormat = true; - //std::cout << "Updated physical stream format:" << std::endl; - //std::cout << " mBitsPerChan = " << testDescription.mBitsPerChannel << std::endl; - //std::cout << " aligned high = " << (testDescription.mFormatFlags & kAudioFormatFlagIsAlignedHigh) << ", isPacked = " << (testDescription.mFormatFlags & kAudioFormatFlagIsPacked) << std::endl; - //std::cout << " bytesPerFrame = " << testDescription.mBytesPerFrame << std::endl; - //std::cout << " sample rate = " << testDescription.mSampleRate << std::endl; - break; - } - } - - if ( !setPhysicalFormat ) { - errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") setting physical data format for device (" << device << ")."; - errorText_ = errorStream_.str(); - return FAILURE; - } - } // done setting virtual/physical formats. - - // Get the stream / device latency. - UInt32 latency; - dataSize = sizeof( UInt32 ); - property.mSelector = kAudioDevicePropertyLatency; - if ( AudioObjectHasProperty( id, &property ) == true ) { - result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, &latency ); - if ( result == kAudioHardwareNoError ) stream_.latency[ mode ] = latency; - else { - errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") getting device latency for device (" << device << ")."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - } - } - - // Byte-swapping: According to AudioHardware.h, the stream data will - // always be presented in native-endian format, so we should never - // need to byte swap. - stream_.doByteSwap[mode] = false; - - // From the CoreAudio documentation, PCM data must be supplied as - // 32-bit floats. - stream_.userFormat = format; - stream_.deviceFormat[mode] = RTAUDIO_FLOAT32; - - if ( streamCount == 1 ) - stream_.nDeviceChannels[mode] = description.mChannelsPerFrame; - else // multiple streams - stream_.nDeviceChannels[mode] = channels; - stream_.nUserChannels[mode] = channels; - stream_.channelOffset[mode] = channelOffset; // offset within a CoreAudio stream - if ( options && options->flags & RTAUDIO_NONINTERLEAVED ) stream_.userInterleaved = false; - else stream_.userInterleaved = true; - stream_.deviceInterleaved[mode] = true; - if ( monoMode == true ) stream_.deviceInterleaved[mode] = false; - - // Set flags for buffer conversion. - stream_.doConvertBuffer[mode] = false; - if ( stream_.userFormat != stream_.deviceFormat[mode] ) - stream_.doConvertBuffer[mode] = true; - if ( stream_.nUserChannels[mode] < stream_.nDeviceChannels[mode] ) - stream_.doConvertBuffer[mode] = true; - if ( streamCount == 1 ) { - if ( stream_.nUserChannels[mode] > 1 && - stream_.userInterleaved != stream_.deviceInterleaved[mode] ) - stream_.doConvertBuffer[mode] = true; - } - else if ( monoMode && stream_.userInterleaved ) - stream_.doConvertBuffer[mode] = true; - - // Allocate our CoreHandle structure for the stream. - CoreHandle *handle = 0; - if ( stream_.apiHandle == 0 ) { - try { - handle = new CoreHandle; - } - catch ( std::bad_alloc& ) { - errorText_ = "RtApiCore::probeDeviceOpen: error allocating CoreHandle memory."; - goto error; - } - - if ( pthread_cond_init( &handle->condition, NULL ) ) { - errorText_ = "RtApiCore::probeDeviceOpen: error initializing pthread condition variable."; - goto error; - } - stream_.apiHandle = (void *) handle; - } - else - handle = (CoreHandle *) stream_.apiHandle; - handle->iStream[mode] = firstStream; - handle->nStreams[mode] = streamCount; - handle->id[mode] = id; - - // Allocate necessary internal buffers. - unsigned long bufferBytes; - bufferBytes = stream_.nUserChannels[mode] * *bufferSize * formatBytes( stream_.userFormat ); - // stream_.userBuffer[mode] = (char *) calloc( bufferBytes, 1 ); - stream_.userBuffer[mode] = (char *) malloc( bufferBytes * sizeof(char) ); - memset( stream_.userBuffer[mode], 0, bufferBytes * sizeof(char) ); - if ( stream_.userBuffer[mode] == NULL ) { - errorText_ = "RtApiCore::probeDeviceOpen: error allocating user buffer memory."; - goto error; - } - - // If possible, we will make use of the CoreAudio stream buffers as - // "device buffers". However, we can't do this if using multiple - // streams. - if ( stream_.doConvertBuffer[mode] && handle->nStreams[mode] > 1 ) { - - bool makeBuffer = true; - bufferBytes = stream_.nDeviceChannels[mode] * formatBytes( stream_.deviceFormat[mode] ); - if ( mode == INPUT ) { - if ( stream_.mode == OUTPUT && stream_.deviceBuffer ) { - unsigned long bytesOut = stream_.nDeviceChannels[0] * formatBytes( stream_.deviceFormat[0] ); - if ( bufferBytes <= bytesOut ) makeBuffer = false; - } - } - - if ( makeBuffer ) { - bufferBytes *= *bufferSize; - if ( stream_.deviceBuffer ) free( stream_.deviceBuffer ); - stream_.deviceBuffer = (char *) calloc( bufferBytes, 1 ); - if ( stream_.deviceBuffer == NULL ) { - errorText_ = "RtApiCore::probeDeviceOpen: error allocating device buffer memory."; - goto error; - } - } - } - - stream_.sampleRate = sampleRate; - stream_.device[mode] = device; - stream_.state = STREAM_STOPPED; - stream_.callbackInfo.object = (void *) this; - - // Setup the buffer conversion information structure. - if ( stream_.doConvertBuffer[mode] ) { - if ( streamCount > 1 ) setConvertInfo( mode, 0 ); - else setConvertInfo( mode, channelOffset ); - } - - if ( mode == INPUT && stream_.mode == OUTPUT && stream_.device[0] == device ) - // Only one callback procedure per device. - stream_.mode = DUPLEX; - else { -#if defined( MAC_OS_X_VERSION_10_5 ) && ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 ) - result = AudioDeviceCreateIOProcID( id, callbackHandler, (void *) &stream_.callbackInfo, &handle->procId[mode] ); -#else - // deprecated in favor of AudioDeviceCreateIOProcID() - result = AudioDeviceAddIOProc( id, callbackHandler, (void *) &stream_.callbackInfo ); -#endif - if ( result != noErr ) { - errorStream_ << "RtApiCore::probeDeviceOpen: system error setting callback for device (" << device << ")."; - errorText_ = errorStream_.str(); - goto error; - } - if ( stream_.mode == OUTPUT && mode == INPUT ) - stream_.mode = DUPLEX; - else - stream_.mode = mode; - } - - // Setup the device property listener for over/underload. - property.mSelector = kAudioDeviceProcessorOverload; - property.mScope = kAudioObjectPropertyScopeGlobal; - result = AudioObjectAddPropertyListener( id, &property, xrunListener, (void *) handle ); - - return SUCCESS; - - error: - if ( handle ) { - pthread_cond_destroy( &handle->condition ); - delete handle; - stream_.apiHandle = 0; - } - - for ( int i=0; i<2; i++ ) { - if ( stream_.userBuffer[i] ) { - free( stream_.userBuffer[i] ); - stream_.userBuffer[i] = 0; - } - } - - if ( stream_.deviceBuffer ) { - free( stream_.deviceBuffer ); - stream_.deviceBuffer = 0; - } - - stream_.state = STREAM_CLOSED; - return FAILURE; -} - -void RtApiCore :: closeStream( void ) -{ - if ( stream_.state == STREAM_CLOSED ) { - errorText_ = "RtApiCore::closeStream(): no open stream to close!"; - error( RtAudioError::WARNING ); - return; - } - - CoreHandle *handle = (CoreHandle *) stream_.apiHandle; - if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) { - if (handle) { - AudioObjectPropertyAddress property = { kAudioHardwarePropertyDevices, - kAudioObjectPropertyScopeGlobal, - kAudioObjectPropertyElementMaster }; - - property.mSelector = kAudioDeviceProcessorOverload; - property.mScope = kAudioObjectPropertyScopeGlobal; - if (AudioObjectRemovePropertyListener( handle->id[0], &property, xrunListener, (void *) handle ) != noErr) { - errorText_ = "RtApiCore::closeStream(): error removing property listener!"; - error( RtAudioError::WARNING ); - } - } - if ( stream_.state == STREAM_RUNNING ) - AudioDeviceStop( handle->id[0], callbackHandler ); -#if defined( MAC_OS_X_VERSION_10_5 ) && ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 ) - AudioDeviceDestroyIOProcID( handle->id[0], handle->procId[0] ); -#else - // deprecated in favor of AudioDeviceDestroyIOProcID() - AudioDeviceRemoveIOProc( handle->id[0], callbackHandler ); -#endif - } - - if ( stream_.mode == INPUT || ( stream_.mode == DUPLEX && stream_.device[0] != stream_.device[1] ) ) { - if (handle) { - AudioObjectPropertyAddress property = { kAudioHardwarePropertyDevices, - kAudioObjectPropertyScopeGlobal, - kAudioObjectPropertyElementMaster }; - - property.mSelector = kAudioDeviceProcessorOverload; - property.mScope = kAudioObjectPropertyScopeGlobal; - if (AudioObjectRemovePropertyListener( handle->id[1], &property, xrunListener, (void *) handle ) != noErr) { - errorText_ = "RtApiCore::closeStream(): error removing property listener!"; - error( RtAudioError::WARNING ); - } - } - if ( stream_.state == STREAM_RUNNING ) - AudioDeviceStop( handle->id[1], callbackHandler ); -#if defined( MAC_OS_X_VERSION_10_5 ) && ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 ) - AudioDeviceDestroyIOProcID( handle->id[1], handle->procId[1] ); -#else - // deprecated in favor of AudioDeviceDestroyIOProcID() - AudioDeviceRemoveIOProc( handle->id[1], callbackHandler ); -#endif - } - - for ( int i=0; i<2; i++ ) { - if ( stream_.userBuffer[i] ) { - free( stream_.userBuffer[i] ); - stream_.userBuffer[i] = 0; - } - } - - if ( stream_.deviceBuffer ) { - free( stream_.deviceBuffer ); - stream_.deviceBuffer = 0; - } - - // Destroy pthread condition variable. - pthread_cond_destroy( &handle->condition ); - delete handle; - stream_.apiHandle = 0; - - stream_.mode = UNINITIALIZED; - stream_.state = STREAM_CLOSED; -} - -void RtApiCore :: startStream( void ) -{ - verifyStream(); - if ( stream_.state == STREAM_RUNNING ) { - errorText_ = "RtApiCore::startStream(): the stream is already running!"; - error( RtAudioError::WARNING ); - return; - } - - OSStatus result = noErr; - CoreHandle *handle = (CoreHandle *) stream_.apiHandle; - if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) { - - result = AudioDeviceStart( handle->id[0], callbackHandler ); - if ( result != noErr ) { - errorStream_ << "RtApiCore::startStream: system error (" << getErrorCode( result ) << ") starting callback procedure on device (" << stream_.device[0] << ")."; - errorText_ = errorStream_.str(); - goto unlock; - } - } - - if ( stream_.mode == INPUT || - ( stream_.mode == DUPLEX && stream_.device[0] != stream_.device[1] ) ) { - - result = AudioDeviceStart( handle->id[1], callbackHandler ); - if ( result != noErr ) { - errorStream_ << "RtApiCore::startStream: system error starting input callback procedure on device (" << stream_.device[1] << ")."; - errorText_ = errorStream_.str(); - goto unlock; - } - } - - handle->drainCounter = 0; - handle->internalDrain = false; - stream_.state = STREAM_RUNNING; - - unlock: - if ( result == noErr ) return; - error( RtAudioError::SYSTEM_ERROR ); -} - -void RtApiCore :: stopStream( void ) -{ - verifyStream(); - if ( stream_.state == STREAM_STOPPED ) { - errorText_ = "RtApiCore::stopStream(): the stream is already stopped!"; - error( RtAudioError::WARNING ); - return; - } - - OSStatus result = noErr; - CoreHandle *handle = (CoreHandle *) stream_.apiHandle; - if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) { - - if ( handle->drainCounter == 0 ) { - handle->drainCounter = 2; - pthread_cond_wait( &handle->condition, &stream_.mutex ); // block until signaled - } - - result = AudioDeviceStop( handle->id[0], callbackHandler ); - if ( result != noErr ) { - errorStream_ << "RtApiCore::stopStream: system error (" << getErrorCode( result ) << ") stopping callback procedure on device (" << stream_.device[0] << ")."; - errorText_ = errorStream_.str(); - goto unlock; - } - } - - if ( stream_.mode == INPUT || ( stream_.mode == DUPLEX && stream_.device[0] != stream_.device[1] ) ) { - - result = AudioDeviceStop( handle->id[1], callbackHandler ); - if ( result != noErr ) { - errorStream_ << "RtApiCore::stopStream: system error (" << getErrorCode( result ) << ") stopping input callback procedure on device (" << stream_.device[1] << ")."; - errorText_ = errorStream_.str(); - goto unlock; - } - } - - stream_.state = STREAM_STOPPED; - - unlock: - if ( result == noErr ) return; - error( RtAudioError::SYSTEM_ERROR ); -} - -void RtApiCore :: abortStream( void ) -{ - verifyStream(); - if ( stream_.state == STREAM_STOPPED ) { - errorText_ = "RtApiCore::abortStream(): the stream is already stopped!"; - error( RtAudioError::WARNING ); - return; - } - - CoreHandle *handle = (CoreHandle *) stream_.apiHandle; - handle->drainCounter = 2; - - stopStream(); -} - -// This function will be called by a spawned thread when the user -// callback function signals that the stream should be stopped or -// aborted. It is better to handle it this way because the -// callbackEvent() function probably should return before the AudioDeviceStop() -// function is called. -static void *coreStopStream( void *ptr ) -{ - CallbackInfo *info = (CallbackInfo *) ptr; - RtApiCore *object = (RtApiCore *) info->object; - - object->stopStream(); - pthread_exit( NULL ); -} - -bool RtApiCore :: callbackEvent( AudioDeviceID deviceId, - const AudioBufferList *inBufferList, - const AudioBufferList *outBufferList ) -{ - if ( stream_.state == STREAM_STOPPED || stream_.state == STREAM_STOPPING ) return SUCCESS; - if ( stream_.state == STREAM_CLOSED ) { - errorText_ = "RtApiCore::callbackEvent(): the stream is closed ... this shouldn't happen!"; - error( RtAudioError::WARNING ); - return FAILURE; - } - - CallbackInfo *info = (CallbackInfo *) &stream_.callbackInfo; - CoreHandle *handle = (CoreHandle *) stream_.apiHandle; - - // Check if we were draining the stream and signal is finished. - if ( handle->drainCounter > 3 ) { - ThreadHandle threadId; - - stream_.state = STREAM_STOPPING; - if ( handle->internalDrain == true ) - pthread_create( &threadId, NULL, coreStopStream, info ); - else // external call to stopStream() - pthread_cond_signal( &handle->condition ); - return SUCCESS; - } - - AudioDeviceID outputDevice = handle->id[0]; - - // Invoke user callback to get fresh output data UNLESS we are - // draining stream or duplex mode AND the input/output devices are - // different AND this function is called for the input device. - if ( handle->drainCounter == 0 && ( stream_.mode != DUPLEX || deviceId == outputDevice ) ) { - RtAudioCallback callback = (RtAudioCallback) info->callback; - double streamTime = getStreamTime(); - RtAudioStreamStatus status = 0; - if ( stream_.mode != INPUT && handle->xrun[0] == true ) { - status |= RTAUDIO_OUTPUT_UNDERFLOW; - handle->xrun[0] = false; - } - if ( stream_.mode != OUTPUT && handle->xrun[1] == true ) { - status |= RTAUDIO_INPUT_OVERFLOW; - handle->xrun[1] = false; - } - - int cbReturnValue = callback( stream_.userBuffer[0], stream_.userBuffer[1], - stream_.bufferSize, streamTime, status, info->userData ); - if ( cbReturnValue == 2 ) { - stream_.state = STREAM_STOPPING; - handle->drainCounter = 2; - abortStream(); - return SUCCESS; - } - else if ( cbReturnValue == 1 ) { - handle->drainCounter = 1; - handle->internalDrain = true; - } - } - - if ( stream_.mode == OUTPUT || ( stream_.mode == DUPLEX && deviceId == outputDevice ) ) { - - if ( handle->drainCounter > 1 ) { // write zeros to the output stream - - if ( handle->nStreams[0] == 1 ) { - memset( outBufferList->mBuffers[handle->iStream[0]].mData, - 0, - outBufferList->mBuffers[handle->iStream[0]].mDataByteSize ); - } - else { // fill multiple streams with zeros - for ( unsigned int i=0; i<handle->nStreams[0]; i++ ) { - memset( outBufferList->mBuffers[handle->iStream[0]+i].mData, - 0, - outBufferList->mBuffers[handle->iStream[0]+i].mDataByteSize ); - } - } - } - else if ( handle->nStreams[0] == 1 ) { - if ( stream_.doConvertBuffer[0] ) { // convert directly to CoreAudio stream buffer - convertBuffer( (char *) outBufferList->mBuffers[handle->iStream[0]].mData, - stream_.userBuffer[0], stream_.convertInfo[0] ); - } - else { // copy from user buffer - memcpy( outBufferList->mBuffers[handle->iStream[0]].mData, - stream_.userBuffer[0], - outBufferList->mBuffers[handle->iStream[0]].mDataByteSize ); - } - } - else { // fill multiple streams - Float32 *inBuffer = (Float32 *) stream_.userBuffer[0]; - if ( stream_.doConvertBuffer[0] ) { - convertBuffer( stream_.deviceBuffer, stream_.userBuffer[0], stream_.convertInfo[0] ); - inBuffer = (Float32 *) stream_.deviceBuffer; - } - - if ( stream_.deviceInterleaved[0] == false ) { // mono mode - UInt32 bufferBytes = outBufferList->mBuffers[handle->iStream[0]].mDataByteSize; - for ( unsigned int i=0; i<stream_.nUserChannels[0]; i++ ) { - memcpy( outBufferList->mBuffers[handle->iStream[0]+i].mData, - (void *)&inBuffer[i*stream_.bufferSize], bufferBytes ); - } - } - else { // fill multiple multi-channel streams with interleaved data - UInt32 streamChannels, channelsLeft, inJump, outJump, inOffset; - Float32 *out, *in; - - bool inInterleaved = ( stream_.userInterleaved ) ? true : false; - UInt32 inChannels = stream_.nUserChannels[0]; - if ( stream_.doConvertBuffer[0] ) { - inInterleaved = true; // device buffer will always be interleaved for nStreams > 1 and not mono mode - inChannels = stream_.nDeviceChannels[0]; - } - - if ( inInterleaved ) inOffset = 1; - else inOffset = stream_.bufferSize; - - channelsLeft = inChannels; - for ( unsigned int i=0; i<handle->nStreams[0]; i++ ) { - in = inBuffer; - out = (Float32 *) outBufferList->mBuffers[handle->iStream[0]+i].mData; - streamChannels = outBufferList->mBuffers[handle->iStream[0]+i].mNumberChannels; - - outJump = 0; - // Account for possible channel offset in first stream - if ( i == 0 && stream_.channelOffset[0] > 0 ) { - streamChannels -= stream_.channelOffset[0]; - outJump = stream_.channelOffset[0]; - out += outJump; - } - - // Account for possible unfilled channels at end of the last stream - if ( streamChannels > channelsLeft ) { - outJump = streamChannels - channelsLeft; - streamChannels = channelsLeft; - } - - // Determine input buffer offsets and skips - if ( inInterleaved ) { - inJump = inChannels; - in += inChannels - channelsLeft; - } - else { - inJump = 1; - in += (inChannels - channelsLeft) * inOffset; - } - - for ( unsigned int i=0; i<stream_.bufferSize; i++ ) { - for ( unsigned int j=0; j<streamChannels; j++ ) { - *out++ = in[j*inOffset]; - } - out += outJump; - in += inJump; - } - channelsLeft -= streamChannels; - } - } - } - } - - // Don't bother draining input - if ( handle->drainCounter ) { - handle->drainCounter++; - goto unlock; - } - - AudioDeviceID inputDevice; - inputDevice = handle->id[1]; - if ( stream_.mode == INPUT || ( stream_.mode == DUPLEX && deviceId == inputDevice ) ) { - - if ( handle->nStreams[1] == 1 ) { - if ( stream_.doConvertBuffer[1] ) { // convert directly from CoreAudio stream buffer - convertBuffer( stream_.userBuffer[1], - (char *) inBufferList->mBuffers[handle->iStream[1]].mData, - stream_.convertInfo[1] ); - } - else { // copy to user buffer - memcpy( stream_.userBuffer[1], - inBufferList->mBuffers[handle->iStream[1]].mData, - inBufferList->mBuffers[handle->iStream[1]].mDataByteSize ); - } - } - else { // read from multiple streams - Float32 *outBuffer = (Float32 *) stream_.userBuffer[1]; - if ( stream_.doConvertBuffer[1] ) outBuffer = (Float32 *) stream_.deviceBuffer; - - if ( stream_.deviceInterleaved[1] == false ) { // mono mode - UInt32 bufferBytes = inBufferList->mBuffers[handle->iStream[1]].mDataByteSize; - for ( unsigned int i=0; i<stream_.nUserChannels[1]; i++ ) { - memcpy( (void *)&outBuffer[i*stream_.bufferSize], - inBufferList->mBuffers[handle->iStream[1]+i].mData, bufferBytes ); - } - } - else { // read from multiple multi-channel streams - UInt32 streamChannels, channelsLeft, inJump, outJump, outOffset; - Float32 *out, *in; - - bool outInterleaved = ( stream_.userInterleaved ) ? true : false; - UInt32 outChannels = stream_.nUserChannels[1]; - if ( stream_.doConvertBuffer[1] ) { - outInterleaved = true; // device buffer will always be interleaved for nStreams > 1 and not mono mode - outChannels = stream_.nDeviceChannels[1]; - } - - if ( outInterleaved ) outOffset = 1; - else outOffset = stream_.bufferSize; - - channelsLeft = outChannels; - for ( unsigned int i=0; i<handle->nStreams[1]; i++ ) { - out = outBuffer; - in = (Float32 *) inBufferList->mBuffers[handle->iStream[1]+i].mData; - streamChannels = inBufferList->mBuffers[handle->iStream[1]+i].mNumberChannels; - - inJump = 0; - // Account for possible channel offset in first stream - if ( i == 0 && stream_.channelOffset[1] > 0 ) { - streamChannels -= stream_.channelOffset[1]; - inJump = stream_.channelOffset[1]; - in += inJump; - } - - // Account for possible unread channels at end of the last stream - if ( streamChannels > channelsLeft ) { - inJump = streamChannels - channelsLeft; - streamChannels = channelsLeft; - } - - // Determine output buffer offsets and skips - if ( outInterleaved ) { - outJump = outChannels; - out += outChannels - channelsLeft; - } - else { - outJump = 1; - out += (outChannels - channelsLeft) * outOffset; - } - - for ( unsigned int i=0; i<stream_.bufferSize; i++ ) { - for ( unsigned int j=0; j<streamChannels; j++ ) { - out[j*outOffset] = *in++; - } - out += outJump; - in += inJump; - } - channelsLeft -= streamChannels; - } - } - - if ( stream_.doConvertBuffer[1] ) { // convert from our internal "device" buffer - convertBuffer( stream_.userBuffer[1], - stream_.deviceBuffer, - stream_.convertInfo[1] ); - } - } - } - - unlock: - //MUTEX_UNLOCK( &stream_.mutex ); - - RtApi::tickStreamTime(); - return SUCCESS; -} - -const char* RtApiCore :: getErrorCode( OSStatus code ) -{ - switch( code ) { - - case kAudioHardwareNotRunningError: - return "kAudioHardwareNotRunningError"; - - case kAudioHardwareUnspecifiedError: - return "kAudioHardwareUnspecifiedError"; - - case kAudioHardwareUnknownPropertyError: - return "kAudioHardwareUnknownPropertyError"; - - case kAudioHardwareBadPropertySizeError: - return "kAudioHardwareBadPropertySizeError"; - - case kAudioHardwareIllegalOperationError: - return "kAudioHardwareIllegalOperationError"; - - case kAudioHardwareBadObjectError: - return "kAudioHardwareBadObjectError"; - - case kAudioHardwareBadDeviceError: - return "kAudioHardwareBadDeviceError"; - - case kAudioHardwareBadStreamError: - return "kAudioHardwareBadStreamError"; - - case kAudioHardwareUnsupportedOperationError: - return "kAudioHardwareUnsupportedOperationError"; - - case kAudioDeviceUnsupportedFormatError: - return "kAudioDeviceUnsupportedFormatError"; - - case kAudioDevicePermissionsError: - return "kAudioDevicePermissionsError"; - - default: - return "CoreAudio unknown error"; - } -} - - //******************** End of __MACOSX_CORE__ *********************// -#endif - -#if defined(__UNIX_JACK__) - -// JACK is a low-latency audio server, originally written for the -// GNU/Linux operating system and now also ported to OS-X. It can -// connect a number of different applications to an audio device, as -// well as allowing them to share audio between themselves. -// -// When using JACK with RtAudio, "devices" refer to JACK clients that -// have ports connected to the server. The JACK server is typically -// started in a terminal as follows: -// -// .jackd -d alsa -d hw:0 -// -// or through an interface program such as qjackctl. Many of the -// parameters normally set for a stream are fixed by the JACK server -// and can be specified when the JACK server is started. In -// particular, -// -// .jackd -d alsa -d hw:0 -r 44100 -p 512 -n 4 -// -// specifies a sample rate of 44100 Hz, a buffer size of 512 sample -// frames, and number of buffers = 4. Once the server is running, it -// is not possible to override these values. If the values are not -// specified in the command-line, the JACK server uses default values. -// -// The JACK server does not have to be running when an instance of -// RtApiJack is created, though the function getDeviceCount() will -// report 0 devices found until JACK has been started. When no -// devices are available (i.e., the JACK server is not running), a -// stream cannot be opened. - -#include <jack/jack.h> -#include <unistd.h> -#include <cstdio> - -// A structure to hold various information related to the Jack API -// implementation. -struct JackHandle { - jack_client_t *client; - jack_port_t **ports[2]; - std::string deviceName[2]; - bool xrun[2]; - pthread_cond_t condition; - int drainCounter; // Tracks callback counts when draining - bool internalDrain; // Indicates if stop is initiated from callback or not. - - JackHandle() - :client(0), drainCounter(0), internalDrain(false) { ports[0] = 0; ports[1] = 0; xrun[0] = false; xrun[1] = false; } -}; - -static void jackSilentError( const char * ) {}; - -RtApiJack :: RtApiJack() -{ - // Nothing to do here. -#if !defined(__RTAUDIO_DEBUG__) - // Turn off Jack's internal error reporting. - jack_set_error_function( &jackSilentError ); -#endif -} - -RtApiJack :: ~RtApiJack() -{ - if ( stream_.state != STREAM_CLOSED ) closeStream(); -} - -unsigned int RtApiJack :: getDeviceCount( void ) -{ - // See if we can become a jack client. - jack_options_t options = (jack_options_t) ( JackNoStartServer ); //JackNullOption; - jack_status_t *status = NULL; - jack_client_t *client = jack_client_open( "RtApiJackCount", options, status ); - if ( client == 0 ) return 0; - - const char **ports; - std::string port, previousPort; - unsigned int nChannels = 0, nDevices = 0; - ports = jack_get_ports( client, NULL, NULL, 0 ); - if ( ports ) { - // Parse the port names up to the first colon (:). - size_t iColon = 0; - do { - port = (char *) ports[ nChannels ]; - iColon = port.find(":"); - if ( iColon != std::string::npos ) { - port = port.substr( 0, iColon + 1 ); - if ( port != previousPort ) { - nDevices++; - previousPort = port; - } - } - } while ( ports[++nChannels] ); - free( ports ); - } - - jack_client_close( client ); - return nDevices; -} - -RtAudio::DeviceInfo RtApiJack :: getDeviceInfo( unsigned int device ) -{ - RtAudio::DeviceInfo info; - info.probed = false; - - jack_options_t options = (jack_options_t) ( JackNoStartServer ); //JackNullOption - jack_status_t *status = NULL; - jack_client_t *client = jack_client_open( "RtApiJackInfo", options, status ); - if ( client == 0 ) { - errorText_ = "RtApiJack::getDeviceInfo: Jack server not found or connection error!"; - error( RtAudioError::WARNING ); - return info; - } - - const char **ports; - std::string port, previousPort; - unsigned int nPorts = 0, nDevices = 0; - ports = jack_get_ports( client, NULL, NULL, 0 ); - if ( ports ) { - // Parse the port names up to the first colon (:). - size_t iColon = 0; - do { - port = (char *) ports[ nPorts ]; - iColon = port.find(":"); - if ( iColon != std::string::npos ) { - port = port.substr( 0, iColon ); - if ( port != previousPort ) { - if ( nDevices == device ) info.name = port; - nDevices++; - previousPort = port; - } - } - } while ( ports[++nPorts] ); - free( ports ); - } - - if ( device >= nDevices ) { - jack_client_close( client ); - errorText_ = "RtApiJack::getDeviceInfo: device ID is invalid!"; - error( RtAudioError::INVALID_USE ); - return info; - } - - // Get the current jack server sample rate. - info.sampleRates.clear(); - - info.preferredSampleRate = jack_get_sample_rate( client ); - info.sampleRates.push_back( info.preferredSampleRate ); - - // Count the available ports containing the client name as device - // channels. Jack "input ports" equal RtAudio output channels. - unsigned int nChannels = 0; - ports = jack_get_ports( client, info.name.c_str(), NULL, JackPortIsInput ); - if ( ports ) { - while ( ports[ nChannels ] ) nChannels++; - free( ports ); - info.outputChannels = nChannels; - } - - // Jack "output ports" equal RtAudio input channels. - nChannels = 0; - ports = jack_get_ports( client, info.name.c_str(), NULL, JackPortIsOutput ); - if ( ports ) { - while ( ports[ nChannels ] ) nChannels++; - free( ports ); - info.inputChannels = nChannels; - } - - if ( info.outputChannels == 0 && info.inputChannels == 0 ) { - jack_client_close(client); - errorText_ = "RtApiJack::getDeviceInfo: error determining Jack input/output channels!"; - error( RtAudioError::WARNING ); - return info; - } - - // If device opens for both playback and capture, we determine the channels. - if ( info.outputChannels > 0 && info.inputChannels > 0 ) - info.duplexChannels = (info.outputChannels > info.inputChannels) ? info.inputChannels : info.outputChannels; - - // Jack always uses 32-bit floats. - info.nativeFormats = RTAUDIO_FLOAT32; - - // Jack doesn't provide default devices so we'll use the first available one. - if ( device == 0 && info.outputChannels > 0 ) - info.isDefaultOutput = true; - if ( device == 0 && info.inputChannels > 0 ) - info.isDefaultInput = true; - - jack_client_close(client); - info.probed = true; - return info; -} - -static int jackCallbackHandler( jack_nframes_t nframes, void *infoPointer ) -{ - CallbackInfo *info = (CallbackInfo *) infoPointer; - - RtApiJack *object = (RtApiJack *) info->object; - if ( object->callbackEvent( (unsigned long) nframes ) == false ) return 1; - - return 0; -} - -// This function will be called by a spawned thread when the Jack -// server signals that it is shutting down. It is necessary to handle -// it this way because the jackShutdown() function must return before -// the jack_deactivate() function (in closeStream()) will return. -static void *jackCloseStream( void *ptr ) -{ - CallbackInfo *info = (CallbackInfo *) ptr; - RtApiJack *object = (RtApiJack *) info->object; - - object->closeStream(); - - pthread_exit( NULL ); -} -static void jackShutdown( void *infoPointer ) -{ - CallbackInfo *info = (CallbackInfo *) infoPointer; - RtApiJack *object = (RtApiJack *) info->object; - - // Check current stream state. If stopped, then we'll assume this - // was called as a result of a call to RtApiJack::stopStream (the - // deactivation of a client handle causes this function to be called). - // If not, we'll assume the Jack server is shutting down or some - // other problem occurred and we should close the stream. - if ( object->isStreamRunning() == false ) return; - - ThreadHandle threadId; - pthread_create( &threadId, NULL, jackCloseStream, info ); - std::cerr << "\nRtApiJack: the Jack server is shutting down this client ... stream stopped and closed!!\n" << std::endl; -} - -static int jackXrun( void *infoPointer ) -{ - JackHandle *handle = (JackHandle *) infoPointer; - - if ( handle->ports[0] ) handle->xrun[0] = true; - if ( handle->ports[1] ) handle->xrun[1] = true; - - return 0; -} - -bool RtApiJack :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, - unsigned int firstChannel, unsigned int sampleRate, - RtAudioFormat format, unsigned int *bufferSize, - RtAudio::StreamOptions *options ) -{ - JackHandle *handle = (JackHandle *) stream_.apiHandle; - - // Look for jack server and try to become a client (only do once per stream). - jack_client_t *client = 0; - if ( mode == OUTPUT || ( mode == INPUT && stream_.mode != OUTPUT ) ) { - jack_options_t jackoptions = (jack_options_t) ( JackNoStartServer ); //JackNullOption; - jack_status_t *status = NULL; - if ( options && !options->streamName.empty() ) - client = jack_client_open( options->streamName.c_str(), jackoptions, status ); - else - client = jack_client_open( "RtApiJack", jackoptions, status ); - if ( client == 0 ) { - errorText_ = "RtApiJack::probeDeviceOpen: Jack server not found or connection error!"; - error( RtAudioError::WARNING ); - return FAILURE; - } - } - else { - // The handle must have been created on an earlier pass. - client = handle->client; - } - - const char **ports; - std::string port, previousPort, deviceName; - unsigned int nPorts = 0, nDevices = 0; - ports = jack_get_ports( client, NULL, NULL, 0 ); - if ( ports ) { - // Parse the port names up to the first colon (:). - size_t iColon = 0; - do { - port = (char *) ports[ nPorts ]; - iColon = port.find(":"); - if ( iColon != std::string::npos ) { - port = port.substr( 0, iColon ); - if ( port != previousPort ) { - if ( nDevices == device ) deviceName = port; - nDevices++; - previousPort = port; - } - } - } while ( ports[++nPorts] ); - free( ports ); - } - - if ( device >= nDevices ) { - errorText_ = "RtApiJack::probeDeviceOpen: device ID is invalid!"; - return FAILURE; - } - - // Count the available ports containing the client name as device - // channels. Jack "input ports" equal RtAudio output channels. - unsigned int nChannels = 0; - unsigned long flag = JackPortIsInput; - if ( mode == INPUT ) flag = JackPortIsOutput; - ports = jack_get_ports( client, deviceName.c_str(), NULL, flag ); - if ( ports ) { - while ( ports[ nChannels ] ) nChannels++; - free( ports ); - } - - // Compare the jack ports for specified client to the requested number of channels. - if ( nChannels < (channels + firstChannel) ) { - errorStream_ << "RtApiJack::probeDeviceOpen: requested number of channels (" << channels << ") + offset (" << firstChannel << ") not found for specified device (" << device << ":" << deviceName << ")."; - errorText_ = errorStream_.str(); - return FAILURE; - } - - // Check the jack server sample rate. - unsigned int jackRate = jack_get_sample_rate( client ); - if ( sampleRate != jackRate ) { - jack_client_close( client ); - errorStream_ << "RtApiJack::probeDeviceOpen: the requested sample rate (" << sampleRate << ") is different than the JACK server rate (" << jackRate << ")."; - errorText_ = errorStream_.str(); - return FAILURE; - } - stream_.sampleRate = jackRate; - - // Get the latency of the JACK port. - ports = jack_get_ports( client, deviceName.c_str(), NULL, flag ); - if ( ports[ firstChannel ] ) { - // Added by Ge Wang - jack_latency_callback_mode_t cbmode = (mode == INPUT ? JackCaptureLatency : JackPlaybackLatency); - // the range (usually the min and max are equal) - jack_latency_range_t latrange; latrange.min = latrange.max = 0; - // get the latency range - jack_port_get_latency_range( jack_port_by_name( client, ports[firstChannel] ), cbmode, &latrange ); - // be optimistic, use the min! - stream_.latency[mode] = latrange.min; - //stream_.latency[mode] = jack_port_get_latency( jack_port_by_name( client, ports[ firstChannel ] ) ); - } - free( ports ); - - // The jack server always uses 32-bit floating-point data. - stream_.deviceFormat[mode] = RTAUDIO_FLOAT32; - stream_.userFormat = format; - - if ( options && options->flags & RTAUDIO_NONINTERLEAVED ) stream_.userInterleaved = false; - else stream_.userInterleaved = true; - - // Jack always uses non-interleaved buffers. - stream_.deviceInterleaved[mode] = false; - - // Jack always provides host byte-ordered data. - stream_.doByteSwap[mode] = false; - - // Get the buffer size. The buffer size and number of buffers - // (periods) is set when the jack server is started. - stream_.bufferSize = (int) jack_get_buffer_size( client ); - *bufferSize = stream_.bufferSize; - - stream_.nDeviceChannels[mode] = channels; - stream_.nUserChannels[mode] = channels; - - // Set flags for buffer conversion. - stream_.doConvertBuffer[mode] = false; - if ( stream_.userFormat != stream_.deviceFormat[mode] ) - stream_.doConvertBuffer[mode] = true; - if ( stream_.userInterleaved != stream_.deviceInterleaved[mode] && - stream_.nUserChannels[mode] > 1 ) - stream_.doConvertBuffer[mode] = true; - - // Allocate our JackHandle structure for the stream. - if ( handle == 0 ) { - try { - handle = new JackHandle; - } - catch ( std::bad_alloc& ) { - errorText_ = "RtApiJack::probeDeviceOpen: error allocating JackHandle memory."; - goto error; - } - - if ( pthread_cond_init(&handle->condition, NULL) ) { - errorText_ = "RtApiJack::probeDeviceOpen: error initializing pthread condition variable."; - goto error; - } - stream_.apiHandle = (void *) handle; - handle->client = client; - } - handle->deviceName[mode] = deviceName; - - // Allocate necessary internal buffers. - unsigned long bufferBytes; - bufferBytes = stream_.nUserChannels[mode] * *bufferSize * formatBytes( stream_.userFormat ); - stream_.userBuffer[mode] = (char *) calloc( bufferBytes, 1 ); - if ( stream_.userBuffer[mode] == NULL ) { - errorText_ = "RtApiJack::probeDeviceOpen: error allocating user buffer memory."; - goto error; - } - - if ( stream_.doConvertBuffer[mode] ) { - - bool makeBuffer = true; - if ( mode == OUTPUT ) - bufferBytes = stream_.nDeviceChannels[0] * formatBytes( stream_.deviceFormat[0] ); - else { // mode == INPUT - bufferBytes = stream_.nDeviceChannels[1] * formatBytes( stream_.deviceFormat[1] ); - if ( stream_.mode == OUTPUT && stream_.deviceBuffer ) { - unsigned long bytesOut = stream_.nDeviceChannels[0] * formatBytes(stream_.deviceFormat[0]); - if ( bufferBytes < bytesOut ) makeBuffer = false; - } - } - - if ( makeBuffer ) { - bufferBytes *= *bufferSize; - if ( stream_.deviceBuffer ) free( stream_.deviceBuffer ); - stream_.deviceBuffer = (char *) calloc( bufferBytes, 1 ); - if ( stream_.deviceBuffer == NULL ) { - errorText_ = "RtApiJack::probeDeviceOpen: error allocating device buffer memory."; - goto error; - } - } - } - - // Allocate memory for the Jack ports (channels) identifiers. - handle->ports[mode] = (jack_port_t **) malloc ( sizeof (jack_port_t *) * channels ); - if ( handle->ports[mode] == NULL ) { - errorText_ = "RtApiJack::probeDeviceOpen: error allocating port memory."; - goto error; - } - - stream_.device[mode] = device; - stream_.channelOffset[mode] = firstChannel; - stream_.state = STREAM_STOPPED; - stream_.callbackInfo.object = (void *) this; - - if ( stream_.mode == OUTPUT && mode == INPUT ) - // We had already set up the stream for output. - stream_.mode = DUPLEX; - else { - stream_.mode = mode; - jack_set_process_callback( handle->client, jackCallbackHandler, (void *) &stream_.callbackInfo ); - jack_set_xrun_callback( handle->client, jackXrun, (void *) &handle ); - jack_on_shutdown( handle->client, jackShutdown, (void *) &stream_.callbackInfo ); - } - - // Register our ports. - char label[64]; - if ( mode == OUTPUT ) { - for ( unsigned int i=0; i<stream_.nUserChannels[0]; i++ ) { - snprintf( label, 64, "outport %d", i ); - handle->ports[0][i] = jack_port_register( handle->client, (const char *)label, - JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0 ); - } - } - else { - for ( unsigned int i=0; i<stream_.nUserChannels[1]; i++ ) { - snprintf( label, 64, "inport %d", i ); - handle->ports[1][i] = jack_port_register( handle->client, (const char *)label, - JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0 ); - } - } - - // Setup the buffer conversion information structure. We don't use - // buffers to do channel offsets, so we override that parameter - // here. - if ( stream_.doConvertBuffer[mode] ) setConvertInfo( mode, 0 ); - - return SUCCESS; - - error: - if ( handle ) { - pthread_cond_destroy( &handle->condition ); - jack_client_close( handle->client ); - - if ( handle->ports[0] ) free( handle->ports[0] ); - if ( handle->ports[1] ) free( handle->ports[1] ); - - delete handle; - stream_.apiHandle = 0; - } - - for ( int i=0; i<2; i++ ) { - if ( stream_.userBuffer[i] ) { - free( stream_.userBuffer[i] ); - stream_.userBuffer[i] = 0; - } - } - - if ( stream_.deviceBuffer ) { - free( stream_.deviceBuffer ); - stream_.deviceBuffer = 0; - } - - return FAILURE; -} - -void RtApiJack :: closeStream( void ) -{ - if ( stream_.state == STREAM_CLOSED ) { - errorText_ = "RtApiJack::closeStream(): no open stream to close!"; - error( RtAudioError::WARNING ); - return; - } - - JackHandle *handle = (JackHandle *) stream_.apiHandle; - if ( handle ) { - - if ( stream_.state == STREAM_RUNNING ) - jack_deactivate( handle->client ); - - jack_client_close( handle->client ); - } - - if ( handle ) { - if ( handle->ports[0] ) free( handle->ports[0] ); - if ( handle->ports[1] ) free( handle->ports[1] ); - pthread_cond_destroy( &handle->condition ); - delete handle; - stream_.apiHandle = 0; - } - - for ( int i=0; i<2; i++ ) { - if ( stream_.userBuffer[i] ) { - free( stream_.userBuffer[i] ); - stream_.userBuffer[i] = 0; - } - } - - if ( stream_.deviceBuffer ) { - free( stream_.deviceBuffer ); - stream_.deviceBuffer = 0; - } - - stream_.mode = UNINITIALIZED; - stream_.state = STREAM_CLOSED; -} - -void RtApiJack :: startStream( void ) -{ - verifyStream(); - if ( stream_.state == STREAM_RUNNING ) { - errorText_ = "RtApiJack::startStream(): the stream is already running!"; - error( RtAudioError::WARNING ); - return; - } - - JackHandle *handle = (JackHandle *) stream_.apiHandle; - int result = jack_activate( handle->client ); - if ( result ) { - errorText_ = "RtApiJack::startStream(): unable to activate JACK client!"; - goto unlock; - } - - const char **ports; - - // Get the list of available ports. - if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) { - result = 1; - ports = jack_get_ports( handle->client, handle->deviceName[0].c_str(), NULL, JackPortIsInput); - if ( ports == NULL) { - errorText_ = "RtApiJack::startStream(): error determining available JACK input ports!"; - goto unlock; - } - - // Now make the port connections. Since RtAudio wasn't designed to - // allow the user to select particular channels of a device, we'll - // just open the first "nChannels" ports with offset. - for ( unsigned int i=0; i<stream_.nUserChannels[0]; i++ ) { - result = 1; - if ( ports[ stream_.channelOffset[0] + i ] ) - result = jack_connect( handle->client, jack_port_name( handle->ports[0][i] ), ports[ stream_.channelOffset[0] + i ] ); - if ( result ) { - free( ports ); - errorText_ = "RtApiJack::startStream(): error connecting output ports!"; - goto unlock; - } - } - free(ports); - } - - if ( stream_.mode == INPUT || stream_.mode == DUPLEX ) { - result = 1; - ports = jack_get_ports( handle->client, handle->deviceName[1].c_str(), NULL, JackPortIsOutput ); - if ( ports == NULL) { - errorText_ = "RtApiJack::startStream(): error determining available JACK output ports!"; - goto unlock; - } - - // Now make the port connections. See note above. - for ( unsigned int i=0; i<stream_.nUserChannels[1]; i++ ) { - result = 1; - if ( ports[ stream_.channelOffset[1] + i ] ) - result = jack_connect( handle->client, ports[ stream_.channelOffset[1] + i ], jack_port_name( handle->ports[1][i] ) ); - if ( result ) { - free( ports ); - errorText_ = "RtApiJack::startStream(): error connecting input ports!"; - goto unlock; - } - } - free(ports); - } - - handle->drainCounter = 0; - handle->internalDrain = false; - stream_.state = STREAM_RUNNING; - - unlock: - if ( result == 0 ) return; - error( RtAudioError::SYSTEM_ERROR ); -} - -void RtApiJack :: stopStream( void ) -{ - verifyStream(); - if ( stream_.state == STREAM_STOPPED ) { - errorText_ = "RtApiJack::stopStream(): the stream is already stopped!"; - error( RtAudioError::WARNING ); - return; - } - - JackHandle *handle = (JackHandle *) stream_.apiHandle; - if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) { - - if ( handle->drainCounter == 0 ) { - handle->drainCounter = 2; - pthread_cond_wait( &handle->condition, &stream_.mutex ); // block until signaled - } - } - - jack_deactivate( handle->client ); - stream_.state = STREAM_STOPPED; -} - -void RtApiJack :: abortStream( void ) -{ - verifyStream(); - if ( stream_.state == STREAM_STOPPED ) { - errorText_ = "RtApiJack::abortStream(): the stream is already stopped!"; - error( RtAudioError::WARNING ); - return; - } - - JackHandle *handle = (JackHandle *) stream_.apiHandle; - handle->drainCounter = 2; - - stopStream(); -} - -// This function will be called by a spawned thread when the user -// callback function signals that the stream should be stopped or -// aborted. It is necessary to handle it this way because the -// callbackEvent() function must return before the jack_deactivate() -// function will return. -static void *jackStopStream( void *ptr ) -{ - CallbackInfo *info = (CallbackInfo *) ptr; - RtApiJack *object = (RtApiJack *) info->object; - - object->stopStream(); - pthread_exit( NULL ); -} - -bool RtApiJack :: callbackEvent( unsigned long nframes ) -{ - if ( stream_.state == STREAM_STOPPED || stream_.state == STREAM_STOPPING ) return SUCCESS; - if ( stream_.state == STREAM_CLOSED ) { - errorText_ = "RtApiCore::callbackEvent(): the stream is closed ... this shouldn't happen!"; - error( RtAudioError::WARNING ); - return FAILURE; - } - if ( stream_.bufferSize != nframes ) { - errorText_ = "RtApiCore::callbackEvent(): the JACK buffer size has changed ... cannot process!"; - error( RtAudioError::WARNING ); - return FAILURE; - } - - CallbackInfo *info = (CallbackInfo *) &stream_.callbackInfo; - JackHandle *handle = (JackHandle *) stream_.apiHandle; - - // Check if we were draining the stream and signal is finished. - if ( handle->drainCounter > 3 ) { - ThreadHandle threadId; - - stream_.state = STREAM_STOPPING; - if ( handle->internalDrain == true ) - pthread_create( &threadId, NULL, jackStopStream, info ); - else - pthread_cond_signal( &handle->condition ); - return SUCCESS; - } - - // Invoke user callback first, to get fresh output data. - if ( handle->drainCounter == 0 ) { - RtAudioCallback callback = (RtAudioCallback) info->callback; - double streamTime = getStreamTime(); - RtAudioStreamStatus status = 0; - if ( stream_.mode != INPUT && handle->xrun[0] == true ) { - status |= RTAUDIO_OUTPUT_UNDERFLOW; - handle->xrun[0] = false; - } - if ( stream_.mode != OUTPUT && handle->xrun[1] == true ) { - status |= RTAUDIO_INPUT_OVERFLOW; - handle->xrun[1] = false; - } - int cbReturnValue = callback( stream_.userBuffer[0], stream_.userBuffer[1], - stream_.bufferSize, streamTime, status, info->userData ); - if ( cbReturnValue == 2 ) { - stream_.state = STREAM_STOPPING; - handle->drainCounter = 2; - ThreadHandle id; - pthread_create( &id, NULL, jackStopStream, info ); - return SUCCESS; - } - else if ( cbReturnValue == 1 ) { - handle->drainCounter = 1; - handle->internalDrain = true; - } - } - - jack_default_audio_sample_t *jackbuffer; - unsigned long bufferBytes = nframes * sizeof( jack_default_audio_sample_t ); - if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) { - - if ( handle->drainCounter > 1 ) { // write zeros to the output stream - - for ( unsigned int i=0; i<stream_.nDeviceChannels[0]; i++ ) { - jackbuffer = (jack_default_audio_sample_t *) jack_port_get_buffer( handle->ports[0][i], (jack_nframes_t) nframes ); - memset( jackbuffer, 0, bufferBytes ); - } - - } - else if ( stream_.doConvertBuffer[0] ) { - - convertBuffer( stream_.deviceBuffer, stream_.userBuffer[0], stream_.convertInfo[0] ); - - for ( unsigned int i=0; i<stream_.nDeviceChannels[0]; i++ ) { - jackbuffer = (jack_default_audio_sample_t *) jack_port_get_buffer( handle->ports[0][i], (jack_nframes_t) nframes ); - memcpy( jackbuffer, &stream_.deviceBuffer[i*bufferBytes], bufferBytes ); - } - } - else { // no buffer conversion - for ( unsigned int i=0; i<stream_.nUserChannels[0]; i++ ) { - jackbuffer = (jack_default_audio_sample_t *) jack_port_get_buffer( handle->ports[0][i], (jack_nframes_t) nframes ); - memcpy( jackbuffer, &stream_.userBuffer[0][i*bufferBytes], bufferBytes ); - } - } - } - - // Don't bother draining input - if ( handle->drainCounter ) { - handle->drainCounter++; - goto unlock; - } - - if ( stream_.mode == INPUT || stream_.mode == DUPLEX ) { - - if ( stream_.doConvertBuffer[1] ) { - for ( unsigned int i=0; i<stream_.nDeviceChannels[1]; i++ ) { - jackbuffer = (jack_default_audio_sample_t *) jack_port_get_buffer( handle->ports[1][i], (jack_nframes_t) nframes ); - memcpy( &stream_.deviceBuffer[i*bufferBytes], jackbuffer, bufferBytes ); - } - convertBuffer( stream_.userBuffer[1], stream_.deviceBuffer, stream_.convertInfo[1] ); - } - else { // no buffer conversion - for ( unsigned int i=0; i<stream_.nUserChannels[1]; i++ ) { - jackbuffer = (jack_default_audio_sample_t *) jack_port_get_buffer( handle->ports[1][i], (jack_nframes_t) nframes ); - memcpy( &stream_.userBuffer[1][i*bufferBytes], jackbuffer, bufferBytes ); - } - } - } - - unlock: - RtApi::tickStreamTime(); - return SUCCESS; -} - //******************** End of __UNIX_JACK__ *********************// -#endif - -#if defined(__WINDOWS_ASIO__) // ASIO API on Windows - -// The ASIO API is designed around a callback scheme, so this -// implementation is similar to that used for OS-X CoreAudio and Linux -// Jack. The primary constraint with ASIO is that it only allows -// access to a single driver at a time. Thus, it is not possible to -// have more than one simultaneous RtAudio stream. -// -// This implementation also requires a number of external ASIO files -// and a few global variables. The ASIO callback scheme does not -// allow for the passing of user data, so we must create a global -// pointer to our callbackInfo structure. -// -// On unix systems, we make use of a pthread condition variable. -// Since there is no equivalent in Windows, I hacked something based -// on information found in -// http://www.cs.wustl.edu/~schmidt/win32-cv-1.html. - -#include "asiosys.h" -#include "asio.h" -#include "iasiothiscallresolver.h" -#include "asiodrivers.h" -#include <cmath> - -static AsioDrivers drivers; -static ASIOCallbacks asioCallbacks; -static ASIODriverInfo driverInfo; -static CallbackInfo *asioCallbackInfo; -static bool asioXRun; - -struct AsioHandle { - int drainCounter; // Tracks callback counts when draining - bool internalDrain; // Indicates if stop is initiated from callback or not. - ASIOBufferInfo *bufferInfos; - HANDLE condition; - - AsioHandle() - :drainCounter(0), internalDrain(false), bufferInfos(0) {} -}; - -// Function declarations (definitions at end of section) -static const char* getAsioErrorString( ASIOError result ); -static void sampleRateChanged( ASIOSampleRate sRate ); -static long asioMessages( long selector, long value, void* message, double* opt ); - -RtApiAsio :: RtApiAsio() -{ - // ASIO cannot run on a multi-threaded appartment. You can call - // CoInitialize beforehand, but it must be for appartment threading - // (in which case, CoInitilialize will return S_FALSE here). - coInitialized_ = false; - HRESULT hr = CoInitialize( NULL ); - if ( FAILED(hr) ) { - errorText_ = "RtApiAsio::ASIO requires a single-threaded appartment. Call CoInitializeEx(0,COINIT_APARTMENTTHREADED)"; - error( RtAudioError::WARNING ); - } - coInitialized_ = true; - - drivers.removeCurrentDriver(); - driverInfo.asioVersion = 2; - - // See note in DirectSound implementation about GetDesktopWindow(). - driverInfo.sysRef = GetForegroundWindow(); -} - -RtApiAsio :: ~RtApiAsio() -{ - if ( stream_.state != STREAM_CLOSED ) closeStream(); - if ( coInitialized_ ) CoUninitialize(); -} - -unsigned int RtApiAsio :: getDeviceCount( void ) -{ - return (unsigned int) drivers.asioGetNumDev(); -} - -RtAudio::DeviceInfo RtApiAsio :: getDeviceInfo( unsigned int device ) -{ - RtAudio::DeviceInfo info; - info.probed = false; - - // Get device ID - unsigned int nDevices = getDeviceCount(); - if ( nDevices == 0 ) { - errorText_ = "RtApiAsio::getDeviceInfo: no devices found!"; - error( RtAudioError::INVALID_USE ); - return info; - } - - if ( device >= nDevices ) { - errorText_ = "RtApiAsio::getDeviceInfo: device ID is invalid!"; - error( RtAudioError::INVALID_USE ); - return info; - } - - // If a stream is already open, we cannot probe other devices. Thus, use the saved results. - if ( stream_.state != STREAM_CLOSED ) { - if ( device >= devices_.size() ) { - errorText_ = "RtApiAsio::getDeviceInfo: device ID was not present before stream was opened."; - error( RtAudioError::WARNING ); - return info; - } - return devices_[ device ]; - } - - char driverName[32]; - ASIOError result = drivers.asioGetDriverName( (int) device, driverName, 32 ); - if ( result != ASE_OK ) { - errorStream_ << "RtApiAsio::getDeviceInfo: unable to get driver name (" << getAsioErrorString( result ) << ")."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - return info; - } - - info.name = driverName; - - if ( !drivers.loadDriver( driverName ) ) { - errorStream_ << "RtApiAsio::getDeviceInfo: unable to load driver (" << driverName << ")."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - return info; - } - - result = ASIOInit( &driverInfo ); - if ( result != ASE_OK ) { - errorStream_ << "RtApiAsio::getDeviceInfo: error (" << getAsioErrorString( result ) << ") initializing driver (" << driverName << ")."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - return info; - } - - // Determine the device channel information. - long inputChannels, outputChannels; - result = ASIOGetChannels( &inputChannels, &outputChannels ); - if ( result != ASE_OK ) { - drivers.removeCurrentDriver(); - errorStream_ << "RtApiAsio::getDeviceInfo: error (" << getAsioErrorString( result ) << ") getting channel count (" << driverName << ")."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - return info; - } - - info.outputChannels = outputChannels; - info.inputChannels = inputChannels; - if ( info.outputChannels > 0 && info.inputChannels > 0 ) - info.duplexChannels = (info.outputChannels > info.inputChannels) ? info.inputChannels : info.outputChannels; - - // Determine the supported sample rates. - info.sampleRates.clear(); - for ( unsigned int i=0; i<MAX_SAMPLE_RATES; i++ ) { - result = ASIOCanSampleRate( (ASIOSampleRate) SAMPLE_RATES[i] ); - if ( result == ASE_OK ) { - info.sampleRates.push_back( SAMPLE_RATES[i] ); - - if ( !info.preferredSampleRate || ( SAMPLE_RATES[i] <= 48000 && SAMPLE_RATES[i] > info.preferredSampleRate ) ) - info.preferredSampleRate = SAMPLE_RATES[i]; - } - } - - // Determine supported data types ... just check first channel and assume rest are the same. - ASIOChannelInfo channelInfo; - channelInfo.channel = 0; - channelInfo.isInput = true; - if ( info.inputChannels <= 0 ) channelInfo.isInput = false; - result = ASIOGetChannelInfo( &channelInfo ); - if ( result != ASE_OK ) { - drivers.removeCurrentDriver(); - errorStream_ << "RtApiAsio::getDeviceInfo: error (" << getAsioErrorString( result ) << ") getting driver channel info (" << driverName << ")."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - return info; - } - - info.nativeFormats = 0; - if ( channelInfo.type == ASIOSTInt16MSB || channelInfo.type == ASIOSTInt16LSB ) - info.nativeFormats |= RTAUDIO_SINT16; - else if ( channelInfo.type == ASIOSTInt32MSB || channelInfo.type == ASIOSTInt32LSB ) - info.nativeFormats |= RTAUDIO_SINT32; - else if ( channelInfo.type == ASIOSTFloat32MSB || channelInfo.type == ASIOSTFloat32LSB ) - info.nativeFormats |= RTAUDIO_FLOAT32; - else if ( channelInfo.type == ASIOSTFloat64MSB || channelInfo.type == ASIOSTFloat64LSB ) - info.nativeFormats |= RTAUDIO_FLOAT64; - else if ( channelInfo.type == ASIOSTInt24MSB || channelInfo.type == ASIOSTInt24LSB ) - info.nativeFormats |= RTAUDIO_SINT24; - - if ( info.outputChannels > 0 ) - if ( getDefaultOutputDevice() == device ) info.isDefaultOutput = true; - if ( info.inputChannels > 0 ) - if ( getDefaultInputDevice() == device ) info.isDefaultInput = true; - - info.probed = true; - drivers.removeCurrentDriver(); - return info; -} - -static void bufferSwitch( long index, ASIOBool /*processNow*/ ) -{ - RtApiAsio *object = (RtApiAsio *) asioCallbackInfo->object; - object->callbackEvent( index ); -} - -void RtApiAsio :: saveDeviceInfo( void ) -{ - devices_.clear(); - - unsigned int nDevices = getDeviceCount(); - devices_.resize( nDevices ); - for ( unsigned int i=0; i<nDevices; i++ ) - devices_[i] = getDeviceInfo( i ); -} - -bool RtApiAsio :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, - unsigned int firstChannel, unsigned int sampleRate, - RtAudioFormat format, unsigned int *bufferSize, - RtAudio::StreamOptions *options ) -{//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - bool isDuplexInput = mode == INPUT && stream_.mode == OUTPUT; - - // For ASIO, a duplex stream MUST use the same driver. - if ( isDuplexInput && stream_.device[0] != device ) { - errorText_ = "RtApiAsio::probeDeviceOpen: an ASIO duplex stream must use the same device for input and output!"; - return FAILURE; - } - - char driverName[32]; - ASIOError result = drivers.asioGetDriverName( (int) device, driverName, 32 ); - if ( result != ASE_OK ) { - errorStream_ << "RtApiAsio::probeDeviceOpen: unable to get driver name (" << getAsioErrorString( result ) << ")."; - errorText_ = errorStream_.str(); - return FAILURE; - } - - // Only load the driver once for duplex stream. - if ( !isDuplexInput ) { - // The getDeviceInfo() function will not work when a stream is open - // because ASIO does not allow multiple devices to run at the same - // time. Thus, we'll probe the system before opening a stream and - // save the results for use by getDeviceInfo(). - this->saveDeviceInfo(); - - if ( !drivers.loadDriver( driverName ) ) { - errorStream_ << "RtApiAsio::probeDeviceOpen: unable to load driver (" << driverName << ")."; - errorText_ = errorStream_.str(); - return FAILURE; - } - - result = ASIOInit( &driverInfo ); - if ( result != ASE_OK ) { - errorStream_ << "RtApiAsio::probeDeviceOpen: error (" << getAsioErrorString( result ) << ") initializing driver (" << driverName << ")."; - errorText_ = errorStream_.str(); - return FAILURE; - } - } - - // keep them before any "goto error", they are used for error cleanup + goto device boundary checks - bool buffersAllocated = false; - AsioHandle *handle = (AsioHandle *) stream_.apiHandle; - unsigned int nChannels; - - - // Check the device channel count. - long inputChannels, outputChannels; - result = ASIOGetChannels( &inputChannels, &outputChannels ); - if ( result != ASE_OK ) { - errorStream_ << "RtApiAsio::probeDeviceOpen: error (" << getAsioErrorString( result ) << ") getting channel count (" << driverName << ")."; - errorText_ = errorStream_.str(); - goto error; - } - - if ( ( mode == OUTPUT && (channels+firstChannel) > (unsigned int) outputChannels) || - ( mode == INPUT && (channels+firstChannel) > (unsigned int) inputChannels) ) { - errorStream_ << "RtApiAsio::probeDeviceOpen: driver (" << driverName << ") does not support requested channel count (" << channels << ") + offset (" << firstChannel << ")."; - errorText_ = errorStream_.str(); - goto error; - } - stream_.nDeviceChannels[mode] = channels; - stream_.nUserChannels[mode] = channels; - stream_.channelOffset[mode] = firstChannel; - - // Verify the sample rate is supported. - result = ASIOCanSampleRate( (ASIOSampleRate) sampleRate ); - if ( result != ASE_OK ) { - errorStream_ << "RtApiAsio::probeDeviceOpen: driver (" << driverName << ") does not support requested sample rate (" << sampleRate << ")."; - errorText_ = errorStream_.str(); - goto error; - } - - // Get the current sample rate - ASIOSampleRate currentRate; - result = ASIOGetSampleRate( ¤tRate ); - if ( result != ASE_OK ) { - errorStream_ << "RtApiAsio::probeDeviceOpen: driver (" << driverName << ") error getting sample rate."; - errorText_ = errorStream_.str(); - goto error; - } - - // Set the sample rate only if necessary - if ( currentRate != sampleRate ) { - result = ASIOSetSampleRate( (ASIOSampleRate) sampleRate ); - if ( result != ASE_OK ) { - errorStream_ << "RtApiAsio::probeDeviceOpen: driver (" << driverName << ") error setting sample rate (" << sampleRate << ")."; - errorText_ = errorStream_.str(); - goto error; - } - } - - // Determine the driver data type. - ASIOChannelInfo channelInfo; - channelInfo.channel = 0; - if ( mode == OUTPUT ) channelInfo.isInput = false; - else channelInfo.isInput = true; - result = ASIOGetChannelInfo( &channelInfo ); - if ( result != ASE_OK ) { - errorStream_ << "RtApiAsio::probeDeviceOpen: driver (" << driverName << ") error (" << getAsioErrorString( result ) << ") getting data format."; - errorText_ = errorStream_.str(); - goto error; - } - - // Assuming WINDOWS host is always little-endian. - stream_.doByteSwap[mode] = false; - stream_.userFormat = format; - stream_.deviceFormat[mode] = 0; - if ( channelInfo.type == ASIOSTInt16MSB || channelInfo.type == ASIOSTInt16LSB ) { - stream_.deviceFormat[mode] = RTAUDIO_SINT16; - if ( channelInfo.type == ASIOSTInt16MSB ) stream_.doByteSwap[mode] = true; - } - else if ( channelInfo.type == ASIOSTInt32MSB || channelInfo.type == ASIOSTInt32LSB ) { - stream_.deviceFormat[mode] = RTAUDIO_SINT32; - if ( channelInfo.type == ASIOSTInt32MSB ) stream_.doByteSwap[mode] = true; - } - else if ( channelInfo.type == ASIOSTFloat32MSB || channelInfo.type == ASIOSTFloat32LSB ) { - stream_.deviceFormat[mode] = RTAUDIO_FLOAT32; - if ( channelInfo.type == ASIOSTFloat32MSB ) stream_.doByteSwap[mode] = true; - } - else if ( channelInfo.type == ASIOSTFloat64MSB || channelInfo.type == ASIOSTFloat64LSB ) { - stream_.deviceFormat[mode] = RTAUDIO_FLOAT64; - if ( channelInfo.type == ASIOSTFloat64MSB ) stream_.doByteSwap[mode] = true; - } - else if ( channelInfo.type == ASIOSTInt24MSB || channelInfo.type == ASIOSTInt24LSB ) { - stream_.deviceFormat[mode] = RTAUDIO_SINT24; - if ( channelInfo.type == ASIOSTInt24MSB ) stream_.doByteSwap[mode] = true; - } - - if ( stream_.deviceFormat[mode] == 0 ) { - errorStream_ << "RtApiAsio::probeDeviceOpen: driver (" << driverName << ") data format not supported by RtAudio."; - errorText_ = errorStream_.str(); - goto error; - } - - // Set the buffer size. For a duplex stream, this will end up - // setting the buffer size based on the input constraints, which - // should be ok. - long minSize, maxSize, preferSize, granularity; - result = ASIOGetBufferSize( &minSize, &maxSize, &preferSize, &granularity ); - if ( result != ASE_OK ) { - errorStream_ << "RtApiAsio::probeDeviceOpen: driver (" << driverName << ") error (" << getAsioErrorString( result ) << ") getting buffer size."; - errorText_ = errorStream_.str(); - goto error; - } - - if ( isDuplexInput ) { - // When this is the duplex input (output was opened before), then we have to use the same - // buffersize as the output, because it might use the preferred buffer size, which most - // likely wasn't passed as input to this. The buffer sizes have to be identically anyway, - // So instead of throwing an error, make them equal. The caller uses the reference - // to the "bufferSize" param as usual to set up processing buffers. - - *bufferSize = stream_.bufferSize; - - } else { - if ( *bufferSize == 0 ) *bufferSize = preferSize; - else if ( *bufferSize < (unsigned int) minSize ) *bufferSize = (unsigned int) minSize; - else if ( *bufferSize > (unsigned int) maxSize ) *bufferSize = (unsigned int) maxSize; - else if ( granularity == -1 ) { - // Make sure bufferSize is a power of two. - int log2_of_min_size = 0; - int log2_of_max_size = 0; - - for ( unsigned int i = 0; i < sizeof(long) * 8; i++ ) { - if ( minSize & ((long)1 << i) ) log2_of_min_size = i; - if ( maxSize & ((long)1 << i) ) log2_of_max_size = i; - } - - long min_delta = std::abs( (long)*bufferSize - ((long)1 << log2_of_min_size) ); - int min_delta_num = log2_of_min_size; - - for (int i = log2_of_min_size + 1; i <= log2_of_max_size; i++) { - long current_delta = std::abs( (long)*bufferSize - ((long)1 << i) ); - if (current_delta < min_delta) { - min_delta = current_delta; - min_delta_num = i; - } - } - - *bufferSize = ( (unsigned int)1 << min_delta_num ); - if ( *bufferSize < (unsigned int) minSize ) *bufferSize = (unsigned int) minSize; - else if ( *bufferSize > (unsigned int) maxSize ) *bufferSize = (unsigned int) maxSize; - } - else if ( granularity != 0 ) { - // Set to an even multiple of granularity, rounding up. - *bufferSize = (*bufferSize + granularity-1) / granularity * granularity; - } - } - - /* - // we don't use it anymore, see above! - // Just left it here for the case... - if ( isDuplexInput && stream_.bufferSize != *bufferSize ) { - errorText_ = "RtApiAsio::probeDeviceOpen: input/output buffersize discrepancy!"; - goto error; - } - */ - - stream_.bufferSize = *bufferSize; - stream_.nBuffers = 2; - - if ( options && options->flags & RTAUDIO_NONINTERLEAVED ) stream_.userInterleaved = false; - else stream_.userInterleaved = true; - - // ASIO always uses non-interleaved buffers. - stream_.deviceInterleaved[mode] = false; - - // Allocate, if necessary, our AsioHandle structure for the stream. - if ( handle == 0 ) { - try { - handle = new AsioHandle; - } - catch ( std::bad_alloc& ) { - errorText_ = "RtApiAsio::probeDeviceOpen: error allocating AsioHandle memory."; - goto error; - } - handle->bufferInfos = 0; - - // Create a manual-reset event. - handle->condition = CreateEvent( NULL, // no security - TRUE, // manual-reset - FALSE, // non-signaled initially - NULL ); // unnamed - stream_.apiHandle = (void *) handle; - } - - // Create the ASIO internal buffers. Since RtAudio sets up input - // and output separately, we'll have to dispose of previously - // created output buffers for a duplex stream. - if ( mode == INPUT && stream_.mode == OUTPUT ) { - ASIODisposeBuffers(); - if ( handle->bufferInfos ) free( handle->bufferInfos ); - } - - // Allocate, initialize, and save the bufferInfos in our stream callbackInfo structure. - unsigned int i; - nChannels = stream_.nDeviceChannels[0] + stream_.nDeviceChannels[1]; - handle->bufferInfos = (ASIOBufferInfo *) malloc( nChannels * sizeof(ASIOBufferInfo) ); - if ( handle->bufferInfos == NULL ) { - errorStream_ << "RtApiAsio::probeDeviceOpen: error allocating bufferInfo memory for driver (" << driverName << ")."; - errorText_ = errorStream_.str(); - goto error; - } - - ASIOBufferInfo *infos; - infos = handle->bufferInfos; - for ( i=0; i<stream_.nDeviceChannels[0]; i++, infos++ ) { - infos->isInput = ASIOFalse; - infos->channelNum = i + stream_.channelOffset[0]; - infos->buffers[0] = infos->buffers[1] = 0; - } - for ( i=0; i<stream_.nDeviceChannels[1]; i++, infos++ ) { - infos->isInput = ASIOTrue; - infos->channelNum = i + stream_.channelOffset[1]; - infos->buffers[0] = infos->buffers[1] = 0; - } - - // prepare for callbacks - stream_.sampleRate = sampleRate; - stream_.device[mode] = device; - stream_.mode = isDuplexInput ? DUPLEX : mode; - - // store this class instance before registering callbacks, that are going to use it - asioCallbackInfo = &stream_.callbackInfo; - stream_.callbackInfo.object = (void *) this; - - // Set up the ASIO callback structure and create the ASIO data buffers. - asioCallbacks.bufferSwitch = &bufferSwitch; - asioCallbacks.sampleRateDidChange = &sampleRateChanged; - asioCallbacks.asioMessage = &asioMessages; - asioCallbacks.bufferSwitchTimeInfo = NULL; - result = ASIOCreateBuffers( handle->bufferInfos, nChannels, stream_.bufferSize, &asioCallbacks ); - if ( result != ASE_OK ) { - // Standard method failed. This can happen with strict/misbehaving drivers that return valid buffer size ranges - // but only accept the preferred buffer size as parameter for ASIOCreateBuffers. eg. Creatives ASIO driver - // in that case, let's be naïve and try that instead - *bufferSize = preferSize; - stream_.bufferSize = *bufferSize; - result = ASIOCreateBuffers( handle->bufferInfos, nChannels, stream_.bufferSize, &asioCallbacks ); - } - - if ( result != ASE_OK ) { - errorStream_ << "RtApiAsio::probeDeviceOpen: driver (" << driverName << ") error (" << getAsioErrorString( result ) << ") creating buffers."; - errorText_ = errorStream_.str(); - goto error; - } - buffersAllocated = true; - stream_.state = STREAM_STOPPED; - - // Set flags for buffer conversion. - stream_.doConvertBuffer[mode] = false; - if ( stream_.userFormat != stream_.deviceFormat[mode] ) - stream_.doConvertBuffer[mode] = true; - if ( stream_.userInterleaved != stream_.deviceInterleaved[mode] && - stream_.nUserChannels[mode] > 1 ) - stream_.doConvertBuffer[mode] = true; - - // Allocate necessary internal buffers - unsigned long bufferBytes; - bufferBytes = stream_.nUserChannels[mode] * *bufferSize * formatBytes( stream_.userFormat ); - stream_.userBuffer[mode] = (char *) calloc( bufferBytes, 1 ); - if ( stream_.userBuffer[mode] == NULL ) { - errorText_ = "RtApiAsio::probeDeviceOpen: error allocating user buffer memory."; - goto error; - } - - if ( stream_.doConvertBuffer[mode] ) { - - bool makeBuffer = true; - bufferBytes = stream_.nDeviceChannels[mode] * formatBytes( stream_.deviceFormat[mode] ); - if ( isDuplexInput && stream_.deviceBuffer ) { - unsigned long bytesOut = stream_.nDeviceChannels[0] * formatBytes( stream_.deviceFormat[0] ); - if ( bufferBytes <= bytesOut ) makeBuffer = false; - } - - if ( makeBuffer ) { - bufferBytes *= *bufferSize; - if ( stream_.deviceBuffer ) free( stream_.deviceBuffer ); - stream_.deviceBuffer = (char *) calloc( bufferBytes, 1 ); - if ( stream_.deviceBuffer == NULL ) { - errorText_ = "RtApiAsio::probeDeviceOpen: error allocating device buffer memory."; - goto error; - } - } - } - - // Determine device latencies - long inputLatency, outputLatency; - result = ASIOGetLatencies( &inputLatency, &outputLatency ); - if ( result != ASE_OK ) { - errorStream_ << "RtApiAsio::probeDeviceOpen: driver (" << driverName << ") error (" << getAsioErrorString( result ) << ") getting latency."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING); // warn but don't fail - } - else { - stream_.latency[0] = outputLatency; - stream_.latency[1] = inputLatency; - } - - // Setup the buffer conversion information structure. We don't use - // buffers to do channel offsets, so we override that parameter - // here. - if ( stream_.doConvertBuffer[mode] ) setConvertInfo( mode, 0 ); - - return SUCCESS; - - error: - if ( !isDuplexInput ) { - // the cleanup for error in the duplex input, is done by RtApi::openStream - // So we clean up for single channel only - - if ( buffersAllocated ) - ASIODisposeBuffers(); - - drivers.removeCurrentDriver(); - - if ( handle ) { - CloseHandle( handle->condition ); - if ( handle->bufferInfos ) - free( handle->bufferInfos ); - - delete handle; - stream_.apiHandle = 0; - } - - - if ( stream_.userBuffer[mode] ) { - free( stream_.userBuffer[mode] ); - stream_.userBuffer[mode] = 0; - } - - if ( stream_.deviceBuffer ) { - free( stream_.deviceBuffer ); - stream_.deviceBuffer = 0; - } - } - - return FAILURE; -}//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -void RtApiAsio :: closeStream() -{ - if ( stream_.state == STREAM_CLOSED ) { - errorText_ = "RtApiAsio::closeStream(): no open stream to close!"; - error( RtAudioError::WARNING ); - return; - } - - if ( stream_.state == STREAM_RUNNING ) { - stream_.state = STREAM_STOPPED; - ASIOStop(); - } - ASIODisposeBuffers(); - drivers.removeCurrentDriver(); - - AsioHandle *handle = (AsioHandle *) stream_.apiHandle; - if ( handle ) { - CloseHandle( handle->condition ); - if ( handle->bufferInfos ) - free( handle->bufferInfos ); - delete handle; - stream_.apiHandle = 0; - } - - for ( int i=0; i<2; i++ ) { - if ( stream_.userBuffer[i] ) { - free( stream_.userBuffer[i] ); - stream_.userBuffer[i] = 0; - } - } - - if ( stream_.deviceBuffer ) { - free( stream_.deviceBuffer ); - stream_.deviceBuffer = 0; - } - - stream_.mode = UNINITIALIZED; - stream_.state = STREAM_CLOSED; -} - -bool stopThreadCalled = false; - -void RtApiAsio :: startStream() -{ - verifyStream(); - if ( stream_.state == STREAM_RUNNING ) { - errorText_ = "RtApiAsio::startStream(): the stream is already running!"; - error( RtAudioError::WARNING ); - return; - } - - AsioHandle *handle = (AsioHandle *) stream_.apiHandle; - ASIOError result = ASIOStart(); - if ( result != ASE_OK ) { - errorStream_ << "RtApiAsio::startStream: error (" << getAsioErrorString( result ) << ") starting device."; - errorText_ = errorStream_.str(); - goto unlock; - } - - handle->drainCounter = 0; - handle->internalDrain = false; - ResetEvent( handle->condition ); - stream_.state = STREAM_RUNNING; - asioXRun = false; - - unlock: - stopThreadCalled = false; - - if ( result == ASE_OK ) return; - error( RtAudioError::SYSTEM_ERROR ); -} - -void RtApiAsio :: stopStream() -{ - verifyStream(); - if ( stream_.state == STREAM_STOPPED ) { - errorText_ = "RtApiAsio::stopStream(): the stream is already stopped!"; - error( RtAudioError::WARNING ); - return; - } - - AsioHandle *handle = (AsioHandle *) stream_.apiHandle; - if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) { - if ( handle->drainCounter == 0 ) { - handle->drainCounter = 2; - WaitForSingleObject( handle->condition, INFINITE ); // block until signaled - } - } - - stream_.state = STREAM_STOPPED; - - ASIOError result = ASIOStop(); - if ( result != ASE_OK ) { - errorStream_ << "RtApiAsio::stopStream: error (" << getAsioErrorString( result ) << ") stopping device."; - errorText_ = errorStream_.str(); - } - - if ( result == ASE_OK ) return; - error( RtAudioError::SYSTEM_ERROR ); -} - -void RtApiAsio :: abortStream() -{ - verifyStream(); - if ( stream_.state == STREAM_STOPPED ) { - errorText_ = "RtApiAsio::abortStream(): the stream is already stopped!"; - error( RtAudioError::WARNING ); - return; - } - - // The following lines were commented-out because some behavior was - // noted where the device buffers need to be zeroed to avoid - // continuing sound, even when the device buffers are completely - // disposed. So now, calling abort is the same as calling stop. - // AsioHandle *handle = (AsioHandle *) stream_.apiHandle; - // handle->drainCounter = 2; - stopStream(); -} - -// This function will be called by a spawned thread when the user -// callback function signals that the stream should be stopped or -// aborted. It is necessary to handle it this way because the -// callbackEvent() function must return before the ASIOStop() -// function will return. -static unsigned __stdcall asioStopStream( void *ptr ) -{ - CallbackInfo *info = (CallbackInfo *) ptr; - RtApiAsio *object = (RtApiAsio *) info->object; - - object->stopStream(); - _endthreadex( 0 ); - return 0; -} - -bool RtApiAsio :: callbackEvent( long bufferIndex ) -{ - if ( stream_.state == STREAM_STOPPED || stream_.state == STREAM_STOPPING ) return SUCCESS; - if ( stream_.state == STREAM_CLOSED ) { - errorText_ = "RtApiAsio::callbackEvent(): the stream is closed ... this shouldn't happen!"; - error( RtAudioError::WARNING ); - return FAILURE; - } - - CallbackInfo *info = (CallbackInfo *) &stream_.callbackInfo; - AsioHandle *handle = (AsioHandle *) stream_.apiHandle; - - // Check if we were draining the stream and signal if finished. - if ( handle->drainCounter > 3 ) { - - stream_.state = STREAM_STOPPING; - if ( handle->internalDrain == false ) - SetEvent( handle->condition ); - else { // spawn a thread to stop the stream - unsigned threadId; - stream_.callbackInfo.thread = _beginthreadex( NULL, 0, &asioStopStream, - &stream_.callbackInfo, 0, &threadId ); - } - return SUCCESS; - } - - // Invoke user callback to get fresh output data UNLESS we are - // draining stream. - if ( handle->drainCounter == 0 ) { - RtAudioCallback callback = (RtAudioCallback) info->callback; - double streamTime = getStreamTime(); - RtAudioStreamStatus status = 0; - if ( stream_.mode != INPUT && asioXRun == true ) { - status |= RTAUDIO_OUTPUT_UNDERFLOW; - asioXRun = false; - } - if ( stream_.mode != OUTPUT && asioXRun == true ) { - status |= RTAUDIO_INPUT_OVERFLOW; - asioXRun = false; - } - int cbReturnValue = callback( stream_.userBuffer[0], stream_.userBuffer[1], - stream_.bufferSize, streamTime, status, info->userData ); - if ( cbReturnValue == 2 ) { - stream_.state = STREAM_STOPPING; - handle->drainCounter = 2; - unsigned threadId; - stream_.callbackInfo.thread = _beginthreadex( NULL, 0, &asioStopStream, - &stream_.callbackInfo, 0, &threadId ); - return SUCCESS; - } - else if ( cbReturnValue == 1 ) { - handle->drainCounter = 1; - handle->internalDrain = true; - } - } - - unsigned int nChannels, bufferBytes, i, j; - nChannels = stream_.nDeviceChannels[0] + stream_.nDeviceChannels[1]; - if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) { - - bufferBytes = stream_.bufferSize * formatBytes( stream_.deviceFormat[0] ); - - if ( handle->drainCounter > 1 ) { // write zeros to the output stream - - for ( i=0, j=0; i<nChannels; i++ ) { - if ( handle->bufferInfos[i].isInput != ASIOTrue ) - memset( handle->bufferInfos[i].buffers[bufferIndex], 0, bufferBytes ); - } - - } - else if ( stream_.doConvertBuffer[0] ) { - - convertBuffer( stream_.deviceBuffer, stream_.userBuffer[0], stream_.convertInfo[0] ); - if ( stream_.doByteSwap[0] ) - byteSwapBuffer( stream_.deviceBuffer, - stream_.bufferSize * stream_.nDeviceChannels[0], - stream_.deviceFormat[0] ); - - for ( i=0, j=0; i<nChannels; i++ ) { - if ( handle->bufferInfos[i].isInput != ASIOTrue ) - memcpy( handle->bufferInfos[i].buffers[bufferIndex], - &stream_.deviceBuffer[j++*bufferBytes], bufferBytes ); - } - - } - else { - - if ( stream_.doByteSwap[0] ) - byteSwapBuffer( stream_.userBuffer[0], - stream_.bufferSize * stream_.nUserChannels[0], - stream_.userFormat ); - - for ( i=0, j=0; i<nChannels; i++ ) { - if ( handle->bufferInfos[i].isInput != ASIOTrue ) - memcpy( handle->bufferInfos[i].buffers[bufferIndex], - &stream_.userBuffer[0][bufferBytes*j++], bufferBytes ); - } - - } - } - - // Don't bother draining input - if ( handle->drainCounter ) { - handle->drainCounter++; - goto unlock; - } - - if ( stream_.mode == INPUT || stream_.mode == DUPLEX ) { - - bufferBytes = stream_.bufferSize * formatBytes(stream_.deviceFormat[1]); - - if (stream_.doConvertBuffer[1]) { - - // Always interleave ASIO input data. - for ( i=0, j=0; i<nChannels; i++ ) { - if ( handle->bufferInfos[i].isInput == ASIOTrue ) - memcpy( &stream_.deviceBuffer[j++*bufferBytes], - handle->bufferInfos[i].buffers[bufferIndex], - bufferBytes ); - } - - if ( stream_.doByteSwap[1] ) - byteSwapBuffer( stream_.deviceBuffer, - stream_.bufferSize * stream_.nDeviceChannels[1], - stream_.deviceFormat[1] ); - convertBuffer( stream_.userBuffer[1], stream_.deviceBuffer, stream_.convertInfo[1] ); - - } - else { - for ( i=0, j=0; i<nChannels; i++ ) { - if ( handle->bufferInfos[i].isInput == ASIOTrue ) { - memcpy( &stream_.userBuffer[1][bufferBytes*j++], - handle->bufferInfos[i].buffers[bufferIndex], - bufferBytes ); - } - } - - if ( stream_.doByteSwap[1] ) - byteSwapBuffer( stream_.userBuffer[1], - stream_.bufferSize * stream_.nUserChannels[1], - stream_.userFormat ); - } - } - - unlock: - // The following call was suggested by Malte Clasen. While the API - // documentation indicates it should not be required, some device - // drivers apparently do not function correctly without it. - ASIOOutputReady(); - - RtApi::tickStreamTime(); - return SUCCESS; -} - -static void sampleRateChanged( ASIOSampleRate sRate ) -{ - // The ASIO documentation says that this usually only happens during - // external sync. Audio processing is not stopped by the driver, - // actual sample rate might not have even changed, maybe only the - // sample rate status of an AES/EBU or S/PDIF digital input at the - // audio device. - - RtApi *object = (RtApi *) asioCallbackInfo->object; - try { - object->stopStream(); - } - catch ( RtAudioError &exception ) { - std::cerr << "\nRtApiAsio: sampleRateChanged() error (" << exception.getMessage() << ")!\n" << std::endl; - return; - } - - std::cerr << "\nRtApiAsio: driver reports sample rate changed to " << sRate << " ... stream stopped!!!\n" << std::endl; -} - -static long asioMessages( long selector, long value, void* /*message*/, double* /*opt*/ ) -{ - long ret = 0; - - switch( selector ) { - case kAsioSelectorSupported: - if ( value == kAsioResetRequest - || value == kAsioEngineVersion - || value == kAsioResyncRequest - || value == kAsioLatenciesChanged - // The following three were added for ASIO 2.0, you don't - // necessarily have to support them. - || value == kAsioSupportsTimeInfo - || value == kAsioSupportsTimeCode - || value == kAsioSupportsInputMonitor) - ret = 1L; - break; - case kAsioResetRequest: - // Defer the task and perform the reset of the driver during the - // next "safe" situation. You cannot reset the driver right now, - // as this code is called from the driver. Reset the driver is - // done by completely destruct is. I.e. ASIOStop(), - // ASIODisposeBuffers(), Destruction Afterwards you initialize the - // driver again. - std::cerr << "\nRtApiAsio: driver reset requested!!!" << std::endl; - ret = 1L; - break; - case kAsioResyncRequest: - // This informs the application that the driver encountered some - // non-fatal data loss. It is used for synchronization purposes - // of different media. Added mainly to work around the Win16Mutex - // problems in Windows 95/98 with the Windows Multimedia system, - // which could lose data because the Mutex was held too long by - // another thread. However a driver can issue it in other - // situations, too. - // std::cerr << "\nRtApiAsio: driver resync requested!!!" << std::endl; - asioXRun = true; - ret = 1L; - break; - case kAsioLatenciesChanged: - // This will inform the host application that the drivers were - // latencies changed. Beware, it this does not mean that the - // buffer sizes have changed! You might need to update internal - // delay data. - std::cerr << "\nRtApiAsio: driver latency may have changed!!!" << std::endl; - ret = 1L; - break; - case kAsioEngineVersion: - // Return the supported ASIO version of the host application. If - // a host application does not implement this selector, ASIO 1.0 - // is assumed by the driver. - ret = 2L; - break; - case kAsioSupportsTimeInfo: - // Informs the driver whether the - // asioCallbacks.bufferSwitchTimeInfo() callback is supported. - // For compatibility with ASIO 1.0 drivers the host application - // should always support the "old" bufferSwitch method, too. - ret = 0; - break; - case kAsioSupportsTimeCode: - // Informs the driver whether application is interested in time - // code info. If an application does not need to know about time - // code, the driver has less work to do. - ret = 0; - break; - } - return ret; -} - -static const char* getAsioErrorString( ASIOError result ) -{ - struct Messages - { - ASIOError value; - const char*message; - }; - - static const Messages m[] = - { - { ASE_NotPresent, "Hardware input or output is not present or available." }, - { ASE_HWMalfunction, "Hardware is malfunctioning." }, - { ASE_InvalidParameter, "Invalid input parameter." }, - { ASE_InvalidMode, "Invalid mode." }, - { ASE_SPNotAdvancing, "Sample position not advancing." }, - { ASE_NoClock, "Sample clock or rate cannot be determined or is not present." }, - { ASE_NoMemory, "Not enough memory to complete the request." } - }; - - for ( unsigned int i = 0; i < sizeof(m)/sizeof(m[0]); ++i ) - if ( m[i].value == result ) return m[i].message; - - return "Unknown error."; -} - -//******************** End of __WINDOWS_ASIO__ *********************// -#endif - - -#if defined(__WINDOWS_WASAPI__) // Windows WASAPI API - -// Authored by Marcus Tomlinson <themarcustomlinson@gmail.com>, April 2014 -// - Introduces support for the Windows WASAPI API -// - Aims to deliver bit streams to and from hardware at the lowest possible latency, via the absolute minimum buffer sizes required -// - Provides flexible stream configuration to an otherwise strict and inflexible WASAPI interface -// - Includes automatic internal conversion of sample rate and buffer size between hardware and the user - -#ifndef INITGUID - #define INITGUID -#endif -#include <audioclient.h> -#include <avrt.h> -#include <mmdeviceapi.h> -#include <functiondiscoverykeys_devpkey.h> - -//============================================================================= - -#define SAFE_RELEASE( objectPtr )\ -if ( objectPtr )\ -{\ - objectPtr->Release();\ - objectPtr = NULL;\ -} - -typedef HANDLE ( __stdcall *TAvSetMmThreadCharacteristicsPtr )( LPCWSTR TaskName, LPDWORD TaskIndex ); - -//----------------------------------------------------------------------------- - -// WASAPI dictates stream sample rate, format, channel count, and in some cases, buffer size. -// Therefore we must perform all necessary conversions to user buffers in order to satisfy these -// requirements. WasapiBuffer ring buffers are used between HwIn->UserIn and UserOut->HwOut to -// provide intermediate storage for read / write synchronization. -class WasapiBuffer -{ -public: - WasapiBuffer() - : buffer_( NULL ), - bufferSize_( 0 ), - inIndex_( 0 ), - outIndex_( 0 ) {} - - ~WasapiBuffer() { - free( buffer_ ); - } - - // sets the length of the internal ring buffer - void setBufferSize( unsigned int bufferSize, unsigned int formatBytes ) { - free( buffer_ ); - - buffer_ = ( char* ) calloc( bufferSize, formatBytes ); - - bufferSize_ = bufferSize; - inIndex_ = 0; - outIndex_ = 0; - } - - // attempt to push a buffer into the ring buffer at the current "in" index - bool pushBuffer( char* buffer, unsigned int bufferSize, RtAudioFormat format ) - { - if ( !buffer || // incoming buffer is NULL - bufferSize == 0 || // incoming buffer has no data - bufferSize > bufferSize_ ) // incoming buffer too large - { - return false; - } - - unsigned int relOutIndex = outIndex_; - unsigned int inIndexEnd = inIndex_ + bufferSize; - if ( relOutIndex < inIndex_ && inIndexEnd >= bufferSize_ ) { - relOutIndex += bufferSize_; - } - - // "in" index can end on the "out" index but cannot begin at it - if ( inIndex_ <= relOutIndex && inIndexEnd > relOutIndex ) { - return false; // not enough space between "in" index and "out" index - } - - // copy buffer from external to internal - int fromZeroSize = inIndex_ + bufferSize - bufferSize_; - fromZeroSize = fromZeroSize < 0 ? 0 : fromZeroSize; - int fromInSize = bufferSize - fromZeroSize; - - switch( format ) - { - case RTAUDIO_SINT8: - memcpy( &( ( char* ) buffer_ )[inIndex_], buffer, fromInSize * sizeof( char ) ); - memcpy( buffer_, &( ( char* ) buffer )[fromInSize], fromZeroSize * sizeof( char ) ); - break; - case RTAUDIO_SINT16: - memcpy( &( ( short* ) buffer_ )[inIndex_], buffer, fromInSize * sizeof( short ) ); - memcpy( buffer_, &( ( short* ) buffer )[fromInSize], fromZeroSize * sizeof( short ) ); - break; - case RTAUDIO_SINT24: - memcpy( &( ( S24* ) buffer_ )[inIndex_], buffer, fromInSize * sizeof( S24 ) ); - memcpy( buffer_, &( ( S24* ) buffer )[fromInSize], fromZeroSize * sizeof( S24 ) ); - break; - case RTAUDIO_SINT32: - memcpy( &( ( int* ) buffer_ )[inIndex_], buffer, fromInSize * sizeof( int ) ); - memcpy( buffer_, &( ( int* ) buffer )[fromInSize], fromZeroSize * sizeof( int ) ); - break; - case RTAUDIO_FLOAT32: - memcpy( &( ( float* ) buffer_ )[inIndex_], buffer, fromInSize * sizeof( float ) ); - memcpy( buffer_, &( ( float* ) buffer )[fromInSize], fromZeroSize * sizeof( float ) ); - break; - case RTAUDIO_FLOAT64: - memcpy( &( ( double* ) buffer_ )[inIndex_], buffer, fromInSize * sizeof( double ) ); - memcpy( buffer_, &( ( double* ) buffer )[fromInSize], fromZeroSize * sizeof( double ) ); - break; - } - - // update "in" index - inIndex_ += bufferSize; - inIndex_ %= bufferSize_; - - return true; - } - - // attempt to pull a buffer from the ring buffer from the current "out" index - bool pullBuffer( char* buffer, unsigned int bufferSize, RtAudioFormat format ) - { - if ( !buffer || // incoming buffer is NULL - bufferSize == 0 || // incoming buffer has no data - bufferSize > bufferSize_ ) // incoming buffer too large - { - return false; - } - - unsigned int relInIndex = inIndex_; - unsigned int outIndexEnd = outIndex_ + bufferSize; - if ( relInIndex < outIndex_ && outIndexEnd >= bufferSize_ ) { - relInIndex += bufferSize_; - } - - // "out" index can begin at and end on the "in" index - if ( outIndex_ < relInIndex && outIndexEnd > relInIndex ) { - return false; // not enough space between "out" index and "in" index - } - - // copy buffer from internal to external - int fromZeroSize = outIndex_ + bufferSize - bufferSize_; - fromZeroSize = fromZeroSize < 0 ? 0 : fromZeroSize; - int fromOutSize = bufferSize - fromZeroSize; - - switch( format ) - { - case RTAUDIO_SINT8: - memcpy( buffer, &( ( char* ) buffer_ )[outIndex_], fromOutSize * sizeof( char ) ); - memcpy( &( ( char* ) buffer )[fromOutSize], buffer_, fromZeroSize * sizeof( char ) ); - break; - case RTAUDIO_SINT16: - memcpy( buffer, &( ( short* ) buffer_ )[outIndex_], fromOutSize * sizeof( short ) ); - memcpy( &( ( short* ) buffer )[fromOutSize], buffer_, fromZeroSize * sizeof( short ) ); - break; - case RTAUDIO_SINT24: - memcpy( buffer, &( ( S24* ) buffer_ )[outIndex_], fromOutSize * sizeof( S24 ) ); - memcpy( &( ( S24* ) buffer )[fromOutSize], buffer_, fromZeroSize * sizeof( S24 ) ); - break; - case RTAUDIO_SINT32: - memcpy( buffer, &( ( int* ) buffer_ )[outIndex_], fromOutSize * sizeof( int ) ); - memcpy( &( ( int* ) buffer )[fromOutSize], buffer_, fromZeroSize * sizeof( int ) ); - break; - case RTAUDIO_FLOAT32: - memcpy( buffer, &( ( float* ) buffer_ )[outIndex_], fromOutSize * sizeof( float ) ); - memcpy( &( ( float* ) buffer )[fromOutSize], buffer_, fromZeroSize * sizeof( float ) ); - break; - case RTAUDIO_FLOAT64: - memcpy( buffer, &( ( double* ) buffer_ )[outIndex_], fromOutSize * sizeof( double ) ); - memcpy( &( ( double* ) buffer )[fromOutSize], buffer_, fromZeroSize * sizeof( double ) ); - break; - } - - // update "out" index - outIndex_ += bufferSize; - outIndex_ %= bufferSize_; - - return true; - } - -private: - char* buffer_; - unsigned int bufferSize_; - unsigned int inIndex_; - unsigned int outIndex_; -}; - -//----------------------------------------------------------------------------- - -// In order to satisfy WASAPI's buffer requirements, we need a means of converting sample rate -// between HW and the user. The convertBufferWasapi function is used to perform this conversion -// between HwIn->UserIn and UserOut->HwOut during the stream callback loop. -// This sample rate converter favors speed over quality, and works best with conversions between -// one rate and its multiple. -void convertBufferWasapi( char* outBuffer, - const char* inBuffer, - const unsigned int& channelCount, - const unsigned int& inSampleRate, - const unsigned int& outSampleRate, - const unsigned int& inSampleCount, - unsigned int& outSampleCount, - const RtAudioFormat& format ) -{ - // calculate the new outSampleCount and relative sampleStep - float sampleRatio = ( float ) outSampleRate / inSampleRate; - float sampleStep = 1.0f / sampleRatio; - float inSampleFraction = 0.0f; - - outSampleCount = ( unsigned int ) roundf( inSampleCount * sampleRatio ); - - // frame-by-frame, copy each relative input sample into it's corresponding output sample - for ( unsigned int outSample = 0; outSample < outSampleCount; outSample++ ) - { - unsigned int inSample = ( unsigned int ) inSampleFraction; - - switch ( format ) - { - case RTAUDIO_SINT8: - memcpy( &( ( char* ) outBuffer )[ outSample * channelCount ], &( ( char* ) inBuffer )[ inSample * channelCount ], channelCount * sizeof( char ) ); - break; - case RTAUDIO_SINT16: - memcpy( &( ( short* ) outBuffer )[ outSample * channelCount ], &( ( short* ) inBuffer )[ inSample * channelCount ], channelCount * sizeof( short ) ); - break; - case RTAUDIO_SINT24: - memcpy( &( ( S24* ) outBuffer )[ outSample * channelCount ], &( ( S24* ) inBuffer )[ inSample * channelCount ], channelCount * sizeof( S24 ) ); - break; - case RTAUDIO_SINT32: - memcpy( &( ( int* ) outBuffer )[ outSample * channelCount ], &( ( int* ) inBuffer )[ inSample * channelCount ], channelCount * sizeof( int ) ); - break; - case RTAUDIO_FLOAT32: - memcpy( &( ( float* ) outBuffer )[ outSample * channelCount ], &( ( float* ) inBuffer )[ inSample * channelCount ], channelCount * sizeof( float ) ); - break; - case RTAUDIO_FLOAT64: - memcpy( &( ( double* ) outBuffer )[ outSample * channelCount ], &( ( double* ) inBuffer )[ inSample * channelCount ], channelCount * sizeof( double ) ); - break; - } - - // jump to next in sample - inSampleFraction += sampleStep; - } -} - -//----------------------------------------------------------------------------- - -// A structure to hold various information related to the WASAPI implementation. -struct WasapiHandle -{ - IAudioClient* captureAudioClient; - IAudioClient* renderAudioClient; - IAudioCaptureClient* captureClient; - IAudioRenderClient* renderClient; - HANDLE captureEvent; - HANDLE renderEvent; - - WasapiHandle() - : captureAudioClient( NULL ), - renderAudioClient( NULL ), - captureClient( NULL ), - renderClient( NULL ), - captureEvent( NULL ), - renderEvent( NULL ) {} -}; - -//============================================================================= - -RtApiWasapi::RtApiWasapi() - : coInitialized_( false ), deviceEnumerator_( NULL ) -{ - // WASAPI can run either apartment or multi-threaded - HRESULT hr = CoInitialize( NULL ); - if ( !FAILED( hr ) ) - coInitialized_ = true; - - // Instantiate device enumerator - hr = CoCreateInstance( __uuidof( MMDeviceEnumerator ), NULL, - CLSCTX_ALL, __uuidof( IMMDeviceEnumerator ), - ( void** ) &deviceEnumerator_ ); - - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::RtApiWasapi: Unable to instantiate device enumerator"; - error( RtAudioError::DRIVER_ERROR ); - } -} - -//----------------------------------------------------------------------------- - -RtApiWasapi::~RtApiWasapi() -{ - if ( stream_.state != STREAM_CLOSED ) - closeStream(); - - SAFE_RELEASE( deviceEnumerator_ ); - - // If this object previously called CoInitialize() - if ( coInitialized_ ) - CoUninitialize(); -} - -//============================================================================= - -unsigned int RtApiWasapi::getDeviceCount( void ) -{ - unsigned int captureDeviceCount = 0; - unsigned int renderDeviceCount = 0; - - IMMDeviceCollection* captureDevices = NULL; - IMMDeviceCollection* renderDevices = NULL; - - // Count capture devices - errorText_.clear(); - HRESULT hr = deviceEnumerator_->EnumAudioEndpoints( eCapture, DEVICE_STATE_ACTIVE, &captureDevices ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::getDeviceCount: Unable to retrieve capture device collection."; - goto Exit; - } - - hr = captureDevices->GetCount( &captureDeviceCount ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::getDeviceCount: Unable to retrieve capture device count."; - goto Exit; - } - - // Count render devices - hr = deviceEnumerator_->EnumAudioEndpoints( eRender, DEVICE_STATE_ACTIVE, &renderDevices ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::getDeviceCount: Unable to retrieve render device collection."; - goto Exit; - } - - hr = renderDevices->GetCount( &renderDeviceCount ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::getDeviceCount: Unable to retrieve render device count."; - goto Exit; - } - -Exit: - // release all references - SAFE_RELEASE( captureDevices ); - SAFE_RELEASE( renderDevices ); - - if ( errorText_.empty() ) - return captureDeviceCount + renderDeviceCount; - - error( RtAudioError::DRIVER_ERROR ); - return 0; -} - -//----------------------------------------------------------------------------- - -RtAudio::DeviceInfo RtApiWasapi::getDeviceInfo( unsigned int device ) -{ - RtAudio::DeviceInfo info; - unsigned int captureDeviceCount = 0; - unsigned int renderDeviceCount = 0; - std::string defaultDeviceName; - bool isCaptureDevice = false; - - PROPVARIANT deviceNameProp; - PROPVARIANT defaultDeviceNameProp; - - IMMDeviceCollection* captureDevices = NULL; - IMMDeviceCollection* renderDevices = NULL; - IMMDevice* devicePtr = NULL; - IMMDevice* defaultDevicePtr = NULL; - IAudioClient* audioClient = NULL; - IPropertyStore* devicePropStore = NULL; - IPropertyStore* defaultDevicePropStore = NULL; - - WAVEFORMATEX* deviceFormat = NULL; - WAVEFORMATEX* closestMatchFormat = NULL; - - // probed - info.probed = false; - - // Count capture devices - errorText_.clear(); - RtAudioError::Type errorType = RtAudioError::DRIVER_ERROR; - HRESULT hr = deviceEnumerator_->EnumAudioEndpoints( eCapture, DEVICE_STATE_ACTIVE, &captureDevices ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve capture device collection."; - goto Exit; - } - - hr = captureDevices->GetCount( &captureDeviceCount ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve capture device count."; - goto Exit; - } - - // Count render devices - hr = deviceEnumerator_->EnumAudioEndpoints( eRender, DEVICE_STATE_ACTIVE, &renderDevices ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve render device collection."; - goto Exit; - } - - hr = renderDevices->GetCount( &renderDeviceCount ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve render device count."; - goto Exit; - } - - // validate device index - if ( device >= captureDeviceCount + renderDeviceCount ) { - errorText_ = "RtApiWasapi::getDeviceInfo: Invalid device index."; - errorType = RtAudioError::INVALID_USE; - goto Exit; - } - - // determine whether index falls within capture or render devices - if ( device >= renderDeviceCount ) { - hr = captureDevices->Item( device - renderDeviceCount, &devicePtr ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve capture device handle."; - goto Exit; - } - isCaptureDevice = true; - } - else { - hr = renderDevices->Item( device, &devicePtr ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve render device handle."; - goto Exit; - } - isCaptureDevice = false; - } - - // get default device name - if ( isCaptureDevice ) { - hr = deviceEnumerator_->GetDefaultAudioEndpoint( eCapture, eConsole, &defaultDevicePtr ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve default capture device handle."; - goto Exit; - } - } - else { - hr = deviceEnumerator_->GetDefaultAudioEndpoint( eRender, eConsole, &defaultDevicePtr ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve default render device handle."; - goto Exit; - } - } - - hr = defaultDevicePtr->OpenPropertyStore( STGM_READ, &defaultDevicePropStore ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::getDeviceInfo: Unable to open default device property store."; - goto Exit; - } - PropVariantInit( &defaultDeviceNameProp ); - - hr = defaultDevicePropStore->GetValue( PKEY_Device_FriendlyName, &defaultDeviceNameProp ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve default device property: PKEY_Device_FriendlyName."; - goto Exit; - } - - defaultDeviceName = convertCharPointerToStdString(defaultDeviceNameProp.pwszVal); - - // name - hr = devicePtr->OpenPropertyStore( STGM_READ, &devicePropStore ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::getDeviceInfo: Unable to open device property store."; - goto Exit; - } - - PropVariantInit( &deviceNameProp ); - - hr = devicePropStore->GetValue( PKEY_Device_FriendlyName, &deviceNameProp ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve device property: PKEY_Device_FriendlyName."; - goto Exit; - } - - info.name =convertCharPointerToStdString(deviceNameProp.pwszVal); - - // is default - if ( isCaptureDevice ) { - info.isDefaultInput = info.name == defaultDeviceName; - info.isDefaultOutput = false; - } - else { - info.isDefaultInput = false; - info.isDefaultOutput = info.name == defaultDeviceName; - } - - // channel count - hr = devicePtr->Activate( __uuidof( IAudioClient ), CLSCTX_ALL, NULL, ( void** ) &audioClient ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve device audio client."; - goto Exit; - } - - hr = audioClient->GetMixFormat( &deviceFormat ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve device mix format."; - goto Exit; - } - - if ( isCaptureDevice ) { - info.inputChannels = deviceFormat->nChannels; - info.outputChannels = 0; - info.duplexChannels = 0; - } - else { - info.inputChannels = 0; - info.outputChannels = deviceFormat->nChannels; - info.duplexChannels = 0; - } - - // sample rates - info.sampleRates.clear(); - - // allow support for all sample rates as we have a built-in sample rate converter - for ( unsigned int i = 0; i < MAX_SAMPLE_RATES; i++ ) { - info.sampleRates.push_back( SAMPLE_RATES[i] ); - } - info.preferredSampleRate = deviceFormat->nSamplesPerSec; - - // native format - info.nativeFormats = 0; - - if ( deviceFormat->wFormatTag == WAVE_FORMAT_IEEE_FLOAT || - ( deviceFormat->wFormatTag == WAVE_FORMAT_EXTENSIBLE && - ( ( WAVEFORMATEXTENSIBLE* ) deviceFormat )->SubFormat == KSDATAFORMAT_SUBTYPE_IEEE_FLOAT ) ) - { - if ( deviceFormat->wBitsPerSample == 32 ) { - info.nativeFormats |= RTAUDIO_FLOAT32; - } - else if ( deviceFormat->wBitsPerSample == 64 ) { - info.nativeFormats |= RTAUDIO_FLOAT64; - } - } - else if ( deviceFormat->wFormatTag == WAVE_FORMAT_PCM || - ( deviceFormat->wFormatTag == WAVE_FORMAT_EXTENSIBLE && - ( ( WAVEFORMATEXTENSIBLE* ) deviceFormat )->SubFormat == KSDATAFORMAT_SUBTYPE_PCM ) ) - { - if ( deviceFormat->wBitsPerSample == 8 ) { - info.nativeFormats |= RTAUDIO_SINT8; - } - else if ( deviceFormat->wBitsPerSample == 16 ) { - info.nativeFormats |= RTAUDIO_SINT16; - } - else if ( deviceFormat->wBitsPerSample == 24 ) { - info.nativeFormats |= RTAUDIO_SINT24; - } - else if ( deviceFormat->wBitsPerSample == 32 ) { - info.nativeFormats |= RTAUDIO_SINT32; - } - } - - // probed - info.probed = true; - -Exit: - // release all references - PropVariantClear( &deviceNameProp ); - PropVariantClear( &defaultDeviceNameProp ); - - SAFE_RELEASE( captureDevices ); - SAFE_RELEASE( renderDevices ); - SAFE_RELEASE( devicePtr ); - SAFE_RELEASE( defaultDevicePtr ); - SAFE_RELEASE( audioClient ); - SAFE_RELEASE( devicePropStore ); - SAFE_RELEASE( defaultDevicePropStore ); - - CoTaskMemFree( deviceFormat ); - CoTaskMemFree( closestMatchFormat ); - - if ( !errorText_.empty() ) - error( errorType ); - return info; -} - -//----------------------------------------------------------------------------- - -unsigned int RtApiWasapi::getDefaultOutputDevice( void ) -{ - for ( unsigned int i = 0; i < getDeviceCount(); i++ ) { - if ( getDeviceInfo( i ).isDefaultOutput ) { - return i; - } - } - - return 0; -} - -//----------------------------------------------------------------------------- - -unsigned int RtApiWasapi::getDefaultInputDevice( void ) -{ - for ( unsigned int i = 0; i < getDeviceCount(); i++ ) { - if ( getDeviceInfo( i ).isDefaultInput ) { - return i; - } - } - - return 0; -} - -//----------------------------------------------------------------------------- - -void RtApiWasapi::closeStream( void ) -{ - if ( stream_.state == STREAM_CLOSED ) { - errorText_ = "RtApiWasapi::closeStream: No open stream to close."; - error( RtAudioError::WARNING ); - return; - } - - if ( stream_.state != STREAM_STOPPED ) - stopStream(); - - // clean up stream memory - SAFE_RELEASE( ( ( WasapiHandle* ) stream_.apiHandle )->captureAudioClient ) - SAFE_RELEASE( ( ( WasapiHandle* ) stream_.apiHandle )->renderAudioClient ) - - SAFE_RELEASE( ( ( WasapiHandle* ) stream_.apiHandle )->captureClient ) - SAFE_RELEASE( ( ( WasapiHandle* ) stream_.apiHandle )->renderClient ) - - if ( ( ( WasapiHandle* ) stream_.apiHandle )->captureEvent ) - CloseHandle( ( ( WasapiHandle* ) stream_.apiHandle )->captureEvent ); - - if ( ( ( WasapiHandle* ) stream_.apiHandle )->renderEvent ) - CloseHandle( ( ( WasapiHandle* ) stream_.apiHandle )->renderEvent ); - - delete ( WasapiHandle* ) stream_.apiHandle; - stream_.apiHandle = NULL; - - for ( int i = 0; i < 2; i++ ) { - if ( stream_.userBuffer[i] ) { - free( stream_.userBuffer[i] ); - stream_.userBuffer[i] = 0; - } - } - - if ( stream_.deviceBuffer ) { - free( stream_.deviceBuffer ); - stream_.deviceBuffer = 0; - } - - // update stream state - stream_.state = STREAM_CLOSED; -} - -//----------------------------------------------------------------------------- - -void RtApiWasapi::startStream( void ) -{ - verifyStream(); - - if ( stream_.state == STREAM_RUNNING ) { - errorText_ = "RtApiWasapi::startStream: The stream is already running."; - error( RtAudioError::WARNING ); - return; - } - - // update stream state - stream_.state = STREAM_RUNNING; - - // create WASAPI stream thread - stream_.callbackInfo.thread = ( ThreadHandle ) CreateThread( NULL, 0, runWasapiThread, this, CREATE_SUSPENDED, NULL ); - - if ( !stream_.callbackInfo.thread ) { - errorText_ = "RtApiWasapi::startStream: Unable to instantiate callback thread."; - error( RtAudioError::THREAD_ERROR ); - } - else { - SetThreadPriority( ( void* ) stream_.callbackInfo.thread, stream_.callbackInfo.priority ); - ResumeThread( ( void* ) stream_.callbackInfo.thread ); - } -} - -//----------------------------------------------------------------------------- - -void RtApiWasapi::stopStream( void ) -{ - verifyStream(); - - if ( stream_.state == STREAM_STOPPED ) { - errorText_ = "RtApiWasapi::stopStream: The stream is already stopped."; - error( RtAudioError::WARNING ); - return; - } - - // inform stream thread by setting stream state to STREAM_STOPPING - stream_.state = STREAM_STOPPING; - - // wait until stream thread is stopped - while( stream_.state != STREAM_STOPPED ) { - Sleep( 1 ); - } - - // Wait for the last buffer to play before stopping. - Sleep( 1000 * stream_.bufferSize / stream_.sampleRate ); - - // stop capture client if applicable - if ( ( ( WasapiHandle* ) stream_.apiHandle )->captureAudioClient ) { - HRESULT hr = ( ( WasapiHandle* ) stream_.apiHandle )->captureAudioClient->Stop(); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::stopStream: Unable to stop capture stream."; - error( RtAudioError::DRIVER_ERROR ); - return; - } - } - - // stop render client if applicable - if ( ( ( WasapiHandle* ) stream_.apiHandle )->renderAudioClient ) { - HRESULT hr = ( ( WasapiHandle* ) stream_.apiHandle )->renderAudioClient->Stop(); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::stopStream: Unable to stop render stream."; - error( RtAudioError::DRIVER_ERROR ); - return; - } - } - - // close thread handle - if ( stream_.callbackInfo.thread && !CloseHandle( ( void* ) stream_.callbackInfo.thread ) ) { - errorText_ = "RtApiWasapi::stopStream: Unable to close callback thread."; - error( RtAudioError::THREAD_ERROR ); - return; - } - - stream_.callbackInfo.thread = (ThreadHandle) NULL; -} - -//----------------------------------------------------------------------------- - -void RtApiWasapi::abortStream( void ) -{ - verifyStream(); - - if ( stream_.state == STREAM_STOPPED ) { - errorText_ = "RtApiWasapi::abortStream: The stream is already stopped."; - error( RtAudioError::WARNING ); - return; - } - - // inform stream thread by setting stream state to STREAM_STOPPING - stream_.state = STREAM_STOPPING; - - // wait until stream thread is stopped - while ( stream_.state != STREAM_STOPPED ) { - Sleep( 1 ); - } - - // stop capture client if applicable - if ( ( ( WasapiHandle* ) stream_.apiHandle )->captureAudioClient ) { - HRESULT hr = ( ( WasapiHandle* ) stream_.apiHandle )->captureAudioClient->Stop(); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::abortStream: Unable to stop capture stream."; - error( RtAudioError::DRIVER_ERROR ); - return; - } - } - - // stop render client if applicable - if ( ( ( WasapiHandle* ) stream_.apiHandle )->renderAudioClient ) { - HRESULT hr = ( ( WasapiHandle* ) stream_.apiHandle )->renderAudioClient->Stop(); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::abortStream: Unable to stop render stream."; - error( RtAudioError::DRIVER_ERROR ); - return; - } - } - - // close thread handle - if ( stream_.callbackInfo.thread && !CloseHandle( ( void* ) stream_.callbackInfo.thread ) ) { - errorText_ = "RtApiWasapi::abortStream: Unable to close callback thread."; - error( RtAudioError::THREAD_ERROR ); - return; - } - - stream_.callbackInfo.thread = (ThreadHandle) NULL; -} - -//----------------------------------------------------------------------------- - -bool RtApiWasapi::probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, - unsigned int firstChannel, unsigned int sampleRate, - RtAudioFormat format, unsigned int* bufferSize, - RtAudio::StreamOptions* options ) -{ - bool methodResult = FAILURE; - unsigned int captureDeviceCount = 0; - unsigned int renderDeviceCount = 0; - - IMMDeviceCollection* captureDevices = NULL; - IMMDeviceCollection* renderDevices = NULL; - IMMDevice* devicePtr = NULL; - WAVEFORMATEX* deviceFormat = NULL; - unsigned int bufferBytes; - stream_.state = STREAM_STOPPED; - - // create API Handle if not already created - if ( !stream_.apiHandle ) - stream_.apiHandle = ( void* ) new WasapiHandle(); - - // Count capture devices - errorText_.clear(); - RtAudioError::Type errorType = RtAudioError::DRIVER_ERROR; - HRESULT hr = deviceEnumerator_->EnumAudioEndpoints( eCapture, DEVICE_STATE_ACTIVE, &captureDevices ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::probeDeviceOpen: Unable to retrieve capture device collection."; - goto Exit; - } - - hr = captureDevices->GetCount( &captureDeviceCount ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::probeDeviceOpen: Unable to retrieve capture device count."; - goto Exit; - } - - // Count render devices - hr = deviceEnumerator_->EnumAudioEndpoints( eRender, DEVICE_STATE_ACTIVE, &renderDevices ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::probeDeviceOpen: Unable to retrieve render device collection."; - goto Exit; - } - - hr = renderDevices->GetCount( &renderDeviceCount ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::probeDeviceOpen: Unable to retrieve render device count."; - goto Exit; - } - - // validate device index - if ( device >= captureDeviceCount + renderDeviceCount ) { - errorType = RtAudioError::INVALID_USE; - errorText_ = "RtApiWasapi::probeDeviceOpen: Invalid device index."; - goto Exit; - } - - // determine whether index falls within capture or render devices - if ( device >= renderDeviceCount ) { - if ( mode != INPUT ) { - errorType = RtAudioError::INVALID_USE; - errorText_ = "RtApiWasapi::probeDeviceOpen: Capture device selected as output device."; - goto Exit; - } - - // retrieve captureAudioClient from devicePtr - IAudioClient*& captureAudioClient = ( ( WasapiHandle* ) stream_.apiHandle )->captureAudioClient; - - hr = captureDevices->Item( device - renderDeviceCount, &devicePtr ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::probeDeviceOpen: Unable to retrieve capture device handle."; - goto Exit; - } - - hr = devicePtr->Activate( __uuidof( IAudioClient ), CLSCTX_ALL, - NULL, ( void** ) &captureAudioClient ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::probeDeviceOpen: Unable to retrieve device audio client."; - goto Exit; - } - - hr = captureAudioClient->GetMixFormat( &deviceFormat ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::probeDeviceOpen: Unable to retrieve device mix format."; - goto Exit; - } - - stream_.nDeviceChannels[mode] = deviceFormat->nChannels; - captureAudioClient->GetStreamLatency( ( long long* ) &stream_.latency[mode] ); - } - else { - if ( mode != OUTPUT ) { - errorType = RtAudioError::INVALID_USE; - errorText_ = "RtApiWasapi::probeDeviceOpen: Render device selected as input device."; - goto Exit; - } - - // retrieve renderAudioClient from devicePtr - IAudioClient*& renderAudioClient = ( ( WasapiHandle* ) stream_.apiHandle )->renderAudioClient; - - hr = renderDevices->Item( device, &devicePtr ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::probeDeviceOpen: Unable to retrieve render device handle."; - goto Exit; - } - - hr = devicePtr->Activate( __uuidof( IAudioClient ), CLSCTX_ALL, - NULL, ( void** ) &renderAudioClient ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::probeDeviceOpen: Unable to retrieve device audio client."; - goto Exit; - } - - hr = renderAudioClient->GetMixFormat( &deviceFormat ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::probeDeviceOpen: Unable to retrieve device mix format."; - goto Exit; - } - - stream_.nDeviceChannels[mode] = deviceFormat->nChannels; - renderAudioClient->GetStreamLatency( ( long long* ) &stream_.latency[mode] ); - } - - // fill stream data - if ( ( stream_.mode == OUTPUT && mode == INPUT ) || - ( stream_.mode == INPUT && mode == OUTPUT ) ) { - stream_.mode = DUPLEX; - } - else { - stream_.mode = mode; - } - - stream_.device[mode] = device; - stream_.doByteSwap[mode] = false; - stream_.sampleRate = sampleRate; - stream_.bufferSize = *bufferSize; - stream_.nBuffers = 1; - stream_.nUserChannels[mode] = channels; - stream_.channelOffset[mode] = firstChannel; - stream_.userFormat = format; - stream_.deviceFormat[mode] = getDeviceInfo( device ).nativeFormats; - - if ( options && options->flags & RTAUDIO_NONINTERLEAVED ) - stream_.userInterleaved = false; - else - stream_.userInterleaved = true; - stream_.deviceInterleaved[mode] = true; - - // Set flags for buffer conversion. - stream_.doConvertBuffer[mode] = false; - if ( stream_.userFormat != stream_.deviceFormat[mode] || - stream_.nUserChannels != stream_.nDeviceChannels ) - stream_.doConvertBuffer[mode] = true; - else if ( stream_.userInterleaved != stream_.deviceInterleaved[mode] && - stream_.nUserChannels[mode] > 1 ) - stream_.doConvertBuffer[mode] = true; - - if ( stream_.doConvertBuffer[mode] ) - setConvertInfo( mode, 0 ); - - // Allocate necessary internal buffers - bufferBytes = stream_.nUserChannels[mode] * stream_.bufferSize * formatBytes( stream_.userFormat ); - - stream_.userBuffer[mode] = ( char* ) calloc( bufferBytes, 1 ); - if ( !stream_.userBuffer[mode] ) { - errorType = RtAudioError::MEMORY_ERROR; - errorText_ = "RtApiWasapi::probeDeviceOpen: Error allocating user buffer memory."; - goto Exit; - } - - if ( options && options->flags & RTAUDIO_SCHEDULE_REALTIME ) - stream_.callbackInfo.priority = 15; - else - stream_.callbackInfo.priority = 0; - - ///! TODO: RTAUDIO_MINIMIZE_LATENCY // Provide stream buffers directly to callback - ///! TODO: RTAUDIO_HOG_DEVICE // Exclusive mode - - methodResult = SUCCESS; - -Exit: - //clean up - SAFE_RELEASE( captureDevices ); - SAFE_RELEASE( renderDevices ); - SAFE_RELEASE( devicePtr ); - CoTaskMemFree( deviceFormat ); - - // if method failed, close the stream - if ( methodResult == FAILURE ) - closeStream(); - - if ( !errorText_.empty() ) - error( errorType ); - return methodResult; -} - -//============================================================================= - -DWORD WINAPI RtApiWasapi::runWasapiThread( void* wasapiPtr ) -{ - if ( wasapiPtr ) - ( ( RtApiWasapi* ) wasapiPtr )->wasapiThread(); - - return 0; -} - -DWORD WINAPI RtApiWasapi::stopWasapiThread( void* wasapiPtr ) -{ - if ( wasapiPtr ) - ( ( RtApiWasapi* ) wasapiPtr )->stopStream(); - - return 0; -} - -DWORD WINAPI RtApiWasapi::abortWasapiThread( void* wasapiPtr ) -{ - if ( wasapiPtr ) - ( ( RtApiWasapi* ) wasapiPtr )->abortStream(); - - return 0; -} - -//----------------------------------------------------------------------------- - -void RtApiWasapi::wasapiThread() -{ - // as this is a new thread, we must CoInitialize it - CoInitialize( NULL ); - - HRESULT hr; - - IAudioClient* captureAudioClient = ( ( WasapiHandle* ) stream_.apiHandle )->captureAudioClient; - IAudioClient* renderAudioClient = ( ( WasapiHandle* ) stream_.apiHandle )->renderAudioClient; - IAudioCaptureClient* captureClient = ( ( WasapiHandle* ) stream_.apiHandle )->captureClient; - IAudioRenderClient* renderClient = ( ( WasapiHandle* ) stream_.apiHandle )->renderClient; - HANDLE captureEvent = ( ( WasapiHandle* ) stream_.apiHandle )->captureEvent; - HANDLE renderEvent = ( ( WasapiHandle* ) stream_.apiHandle )->renderEvent; - - WAVEFORMATEX* captureFormat = NULL; - WAVEFORMATEX* renderFormat = NULL; - float captureSrRatio = 0.0f; - float renderSrRatio = 0.0f; - WasapiBuffer captureBuffer; - WasapiBuffer renderBuffer; - - // declare local stream variables - RtAudioCallback callback = ( RtAudioCallback ) stream_.callbackInfo.callback; - BYTE* streamBuffer = NULL; - unsigned long captureFlags = 0; - unsigned int bufferFrameCount = 0; - unsigned int numFramesPadding = 0; - unsigned int convBufferSize = 0; - bool callbackPushed = false; - bool callbackPulled = false; - bool callbackStopped = false; - int callbackResult = 0; - - // convBuffer is used to store converted buffers between WASAPI and the user - char* convBuffer = NULL; - unsigned int convBuffSize = 0; - unsigned int deviceBuffSize = 0; - - errorText_.clear(); - RtAudioError::Type errorType = RtAudioError::DRIVER_ERROR; - - // Attempt to assign "Pro Audio" characteristic to thread - HMODULE AvrtDll = LoadLibrary( (LPCTSTR) "AVRT.dll" ); - if ( AvrtDll ) { - DWORD taskIndex = 0; - TAvSetMmThreadCharacteristicsPtr AvSetMmThreadCharacteristicsPtr = ( TAvSetMmThreadCharacteristicsPtr ) GetProcAddress( AvrtDll, "AvSetMmThreadCharacteristicsW" ); - AvSetMmThreadCharacteristicsPtr( L"Pro Audio", &taskIndex ); - FreeLibrary( AvrtDll ); - } - - // start capture stream if applicable - if ( captureAudioClient ) { - hr = captureAudioClient->GetMixFormat( &captureFormat ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::wasapiThread: Unable to retrieve device mix format."; - goto Exit; - } - - captureSrRatio = ( ( float ) captureFormat->nSamplesPerSec / stream_.sampleRate ); - - // initialize capture stream according to desire buffer size - float desiredBufferSize = stream_.bufferSize * captureSrRatio; - REFERENCE_TIME desiredBufferPeriod = ( REFERENCE_TIME ) ( ( float ) desiredBufferSize * 10000000 / captureFormat->nSamplesPerSec ); - - if ( !captureClient ) { - hr = captureAudioClient->Initialize( AUDCLNT_SHAREMODE_SHARED, - AUDCLNT_STREAMFLAGS_EVENTCALLBACK, - desiredBufferPeriod, - desiredBufferPeriod, - captureFormat, - NULL ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::wasapiThread: Unable to initialize capture audio client."; - goto Exit; - } - - hr = captureAudioClient->GetService( __uuidof( IAudioCaptureClient ), - ( void** ) &captureClient ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::wasapiThread: Unable to retrieve capture client handle."; - goto Exit; - } - - // configure captureEvent to trigger on every available capture buffer - captureEvent = CreateEvent( NULL, FALSE, FALSE, NULL ); - if ( !captureEvent ) { - errorType = RtAudioError::SYSTEM_ERROR; - errorText_ = "RtApiWasapi::wasapiThread: Unable to create capture event."; - goto Exit; - } - - hr = captureAudioClient->SetEventHandle( captureEvent ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::wasapiThread: Unable to set capture event handle."; - goto Exit; - } - - ( ( WasapiHandle* ) stream_.apiHandle )->captureClient = captureClient; - ( ( WasapiHandle* ) stream_.apiHandle )->captureEvent = captureEvent; - } - - unsigned int inBufferSize = 0; - hr = captureAudioClient->GetBufferSize( &inBufferSize ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::wasapiThread: Unable to get capture buffer size."; - goto Exit; - } - - // scale outBufferSize according to stream->user sample rate ratio - unsigned int outBufferSize = ( unsigned int ) ( stream_.bufferSize * captureSrRatio ) * stream_.nDeviceChannels[INPUT]; - inBufferSize *= stream_.nDeviceChannels[INPUT]; - - // set captureBuffer size - captureBuffer.setBufferSize( inBufferSize + outBufferSize, formatBytes( stream_.deviceFormat[INPUT] ) ); - - // reset the capture stream - hr = captureAudioClient->Reset(); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::wasapiThread: Unable to reset capture stream."; - goto Exit; - } - - // start the capture stream - hr = captureAudioClient->Start(); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::wasapiThread: Unable to start capture stream."; - goto Exit; - } - } - - // start render stream if applicable - if ( renderAudioClient ) { - hr = renderAudioClient->GetMixFormat( &renderFormat ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::wasapiThread: Unable to retrieve device mix format."; - goto Exit; - } - - renderSrRatio = ( ( float ) renderFormat->nSamplesPerSec / stream_.sampleRate ); - - // initialize render stream according to desire buffer size - float desiredBufferSize = stream_.bufferSize * renderSrRatio; - REFERENCE_TIME desiredBufferPeriod = ( REFERENCE_TIME ) ( ( float ) desiredBufferSize * 10000000 / renderFormat->nSamplesPerSec ); - - if ( !renderClient ) { - hr = renderAudioClient->Initialize( AUDCLNT_SHAREMODE_SHARED, - AUDCLNT_STREAMFLAGS_EVENTCALLBACK, - desiredBufferPeriod, - desiredBufferPeriod, - renderFormat, - NULL ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::wasapiThread: Unable to initialize render audio client."; - goto Exit; - } - - hr = renderAudioClient->GetService( __uuidof( IAudioRenderClient ), - ( void** ) &renderClient ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::wasapiThread: Unable to retrieve render client handle."; - goto Exit; - } - - // configure renderEvent to trigger on every available render buffer - renderEvent = CreateEvent( NULL, FALSE, FALSE, NULL ); - if ( !renderEvent ) { - errorType = RtAudioError::SYSTEM_ERROR; - errorText_ = "RtApiWasapi::wasapiThread: Unable to create render event."; - goto Exit; - } - - hr = renderAudioClient->SetEventHandle( renderEvent ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::wasapiThread: Unable to set render event handle."; - goto Exit; - } - - ( ( WasapiHandle* ) stream_.apiHandle )->renderClient = renderClient; - ( ( WasapiHandle* ) stream_.apiHandle )->renderEvent = renderEvent; - } - - unsigned int outBufferSize = 0; - hr = renderAudioClient->GetBufferSize( &outBufferSize ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::wasapiThread: Unable to get render buffer size."; - goto Exit; - } - - // scale inBufferSize according to user->stream sample rate ratio - unsigned int inBufferSize = ( unsigned int ) ( stream_.bufferSize * renderSrRatio ) * stream_.nDeviceChannels[OUTPUT]; - outBufferSize *= stream_.nDeviceChannels[OUTPUT]; - - // set renderBuffer size - renderBuffer.setBufferSize( inBufferSize + outBufferSize, formatBytes( stream_.deviceFormat[OUTPUT] ) ); - - // reset the render stream - hr = renderAudioClient->Reset(); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::wasapiThread: Unable to reset render stream."; - goto Exit; - } - - // start the render stream - hr = renderAudioClient->Start(); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::wasapiThread: Unable to start render stream."; - goto Exit; - } - } - - if ( stream_.mode == INPUT ) { - convBuffSize = ( size_t ) ( stream_.bufferSize * captureSrRatio ) * stream_.nDeviceChannels[INPUT] * formatBytes( stream_.deviceFormat[INPUT] ); - deviceBuffSize = stream_.bufferSize * stream_.nDeviceChannels[INPUT] * formatBytes( stream_.deviceFormat[INPUT] ); - } - else if ( stream_.mode == OUTPUT ) { - convBuffSize = ( size_t ) ( stream_.bufferSize * renderSrRatio ) * stream_.nDeviceChannels[OUTPUT] * formatBytes( stream_.deviceFormat[OUTPUT] ); - deviceBuffSize = stream_.bufferSize * stream_.nDeviceChannels[OUTPUT] * formatBytes( stream_.deviceFormat[OUTPUT] ); - } - else if ( stream_.mode == DUPLEX ) { - convBuffSize = std::max( ( size_t ) ( stream_.bufferSize * captureSrRatio ) * stream_.nDeviceChannels[INPUT] * formatBytes( stream_.deviceFormat[INPUT] ), - ( size_t ) ( stream_.bufferSize * renderSrRatio ) * stream_.nDeviceChannels[OUTPUT] * formatBytes( stream_.deviceFormat[OUTPUT] ) ); - deviceBuffSize = std::max( stream_.bufferSize * stream_.nDeviceChannels[INPUT] * formatBytes( stream_.deviceFormat[INPUT] ), - stream_.bufferSize * stream_.nDeviceChannels[OUTPUT] * formatBytes( stream_.deviceFormat[OUTPUT] ) ); - } - - convBuffer = ( char* ) malloc( convBuffSize ); - stream_.deviceBuffer = ( char* ) malloc( deviceBuffSize ); - if ( !convBuffer || !stream_.deviceBuffer ) { - errorType = RtAudioError::MEMORY_ERROR; - errorText_ = "RtApiWasapi::wasapiThread: Error allocating device buffer memory."; - goto Exit; - } - - // stream process loop - while ( stream_.state != STREAM_STOPPING ) { - if ( !callbackPulled ) { - // Callback Input - // ============== - // 1. Pull callback buffer from inputBuffer - // 2. If 1. was successful: Convert callback buffer to user sample rate and channel count - // Convert callback buffer to user format - - if ( captureAudioClient ) { - // Pull callback buffer from inputBuffer - callbackPulled = captureBuffer.pullBuffer( convBuffer, - ( unsigned int ) ( stream_.bufferSize * captureSrRatio ) * stream_.nDeviceChannels[INPUT], - stream_.deviceFormat[INPUT] ); - - if ( callbackPulled ) { - // Convert callback buffer to user sample rate - convertBufferWasapi( stream_.deviceBuffer, - convBuffer, - stream_.nDeviceChannels[INPUT], - captureFormat->nSamplesPerSec, - stream_.sampleRate, - ( unsigned int ) ( stream_.bufferSize * captureSrRatio ), - convBufferSize, - stream_.deviceFormat[INPUT] ); - - if ( stream_.doConvertBuffer[INPUT] ) { - // Convert callback buffer to user format - convertBuffer( stream_.userBuffer[INPUT], - stream_.deviceBuffer, - stream_.convertInfo[INPUT] ); - } - else { - // no further conversion, simple copy deviceBuffer to userBuffer - memcpy( stream_.userBuffer[INPUT], - stream_.deviceBuffer, - stream_.bufferSize * stream_.nUserChannels[INPUT] * formatBytes( stream_.userFormat ) ); - } - } - } - else { - // if there is no capture stream, set callbackPulled flag - callbackPulled = true; - } - - // Execute Callback - // ================ - // 1. Execute user callback method - // 2. Handle return value from callback - - // if callback has not requested the stream to stop - if ( callbackPulled && !callbackStopped ) { - // Execute user callback method - callbackResult = callback( stream_.userBuffer[OUTPUT], - stream_.userBuffer[INPUT], - stream_.bufferSize, - getStreamTime(), - captureFlags & AUDCLNT_BUFFERFLAGS_DATA_DISCONTINUITY ? RTAUDIO_INPUT_OVERFLOW : 0, - stream_.callbackInfo.userData ); - - // Handle return value from callback - if ( callbackResult == 1 ) { - // instantiate a thread to stop this thread - HANDLE threadHandle = CreateThread( NULL, 0, stopWasapiThread, this, 0, NULL ); - if ( !threadHandle ) { - errorType = RtAudioError::THREAD_ERROR; - errorText_ = "RtApiWasapi::wasapiThread: Unable to instantiate stream stop thread."; - goto Exit; - } - else if ( !CloseHandle( threadHandle ) ) { - errorType = RtAudioError::THREAD_ERROR; - errorText_ = "RtApiWasapi::wasapiThread: Unable to close stream stop thread handle."; - goto Exit; - } - - callbackStopped = true; - } - else if ( callbackResult == 2 ) { - // instantiate a thread to stop this thread - HANDLE threadHandle = CreateThread( NULL, 0, abortWasapiThread, this, 0, NULL ); - if ( !threadHandle ) { - errorType = RtAudioError::THREAD_ERROR; - errorText_ = "RtApiWasapi::wasapiThread: Unable to instantiate stream abort thread."; - goto Exit; - } - else if ( !CloseHandle( threadHandle ) ) { - errorType = RtAudioError::THREAD_ERROR; - errorText_ = "RtApiWasapi::wasapiThread: Unable to close stream abort thread handle."; - goto Exit; - } - - callbackStopped = true; - } - } - } - - // Callback Output - // =============== - // 1. Convert callback buffer to stream format - // 2. Convert callback buffer to stream sample rate and channel count - // 3. Push callback buffer into outputBuffer - - if ( renderAudioClient && callbackPulled ) { - if ( stream_.doConvertBuffer[OUTPUT] ) { - // Convert callback buffer to stream format - convertBuffer( stream_.deviceBuffer, - stream_.userBuffer[OUTPUT], - stream_.convertInfo[OUTPUT] ); - - } - - // Convert callback buffer to stream sample rate - convertBufferWasapi( convBuffer, - stream_.deviceBuffer, - stream_.nDeviceChannels[OUTPUT], - stream_.sampleRate, - renderFormat->nSamplesPerSec, - stream_.bufferSize, - convBufferSize, - stream_.deviceFormat[OUTPUT] ); - - // Push callback buffer into outputBuffer - callbackPushed = renderBuffer.pushBuffer( convBuffer, - convBufferSize * stream_.nDeviceChannels[OUTPUT], - stream_.deviceFormat[OUTPUT] ); - } - else { - // if there is no render stream, set callbackPushed flag - callbackPushed = true; - } - - // Stream Capture - // ============== - // 1. Get capture buffer from stream - // 2. Push capture buffer into inputBuffer - // 3. If 2. was successful: Release capture buffer - - if ( captureAudioClient ) { - // if the callback input buffer was not pulled from captureBuffer, wait for next capture event - if ( !callbackPulled ) { - WaitForSingleObject( captureEvent, INFINITE ); - } - - // Get capture buffer from stream - hr = captureClient->GetBuffer( &streamBuffer, - &bufferFrameCount, - &captureFlags, NULL, NULL ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::wasapiThread: Unable to retrieve capture buffer."; - goto Exit; - } - - if ( bufferFrameCount != 0 ) { - // Push capture buffer into inputBuffer - if ( captureBuffer.pushBuffer( ( char* ) streamBuffer, - bufferFrameCount * stream_.nDeviceChannels[INPUT], - stream_.deviceFormat[INPUT] ) ) - { - // Release capture buffer - hr = captureClient->ReleaseBuffer( bufferFrameCount ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::wasapiThread: Unable to release capture buffer."; - goto Exit; - } - } - else - { - // Inform WASAPI that capture was unsuccessful - hr = captureClient->ReleaseBuffer( 0 ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::wasapiThread: Unable to release capture buffer."; - goto Exit; - } - } - } - else - { - // Inform WASAPI that capture was unsuccessful - hr = captureClient->ReleaseBuffer( 0 ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::wasapiThread: Unable to release capture buffer."; - goto Exit; - } - } - } - - // Stream Render - // ============= - // 1. Get render buffer from stream - // 2. Pull next buffer from outputBuffer - // 3. If 2. was successful: Fill render buffer with next buffer - // Release render buffer - - if ( renderAudioClient ) { - // if the callback output buffer was not pushed to renderBuffer, wait for next render event - if ( callbackPulled && !callbackPushed ) { - WaitForSingleObject( renderEvent, INFINITE ); - } - - // Get render buffer from stream - hr = renderAudioClient->GetBufferSize( &bufferFrameCount ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::wasapiThread: Unable to retrieve render buffer size."; - goto Exit; - } - - hr = renderAudioClient->GetCurrentPadding( &numFramesPadding ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::wasapiThread: Unable to retrieve render buffer padding."; - goto Exit; - } - - bufferFrameCount -= numFramesPadding; - - if ( bufferFrameCount != 0 ) { - hr = renderClient->GetBuffer( bufferFrameCount, &streamBuffer ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::wasapiThread: Unable to retrieve render buffer."; - goto Exit; - } - - // Pull next buffer from outputBuffer - // Fill render buffer with next buffer - if ( renderBuffer.pullBuffer( ( char* ) streamBuffer, - bufferFrameCount * stream_.nDeviceChannels[OUTPUT], - stream_.deviceFormat[OUTPUT] ) ) - { - // Release render buffer - hr = renderClient->ReleaseBuffer( bufferFrameCount, 0 ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::wasapiThread: Unable to release render buffer."; - goto Exit; - } - } - else - { - // Inform WASAPI that render was unsuccessful - hr = renderClient->ReleaseBuffer( 0, 0 ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::wasapiThread: Unable to release render buffer."; - goto Exit; - } - } - } - else - { - // Inform WASAPI that render was unsuccessful - hr = renderClient->ReleaseBuffer( 0, 0 ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::wasapiThread: Unable to release render buffer."; - goto Exit; - } - } - } - - // if the callback buffer was pushed renderBuffer reset callbackPulled flag - if ( callbackPushed ) { - callbackPulled = false; - // tick stream time - RtApi::tickStreamTime(); - } - - } - -Exit: - // clean up - CoTaskMemFree( captureFormat ); - CoTaskMemFree( renderFormat ); - - free ( convBuffer ); - - CoUninitialize(); - - // update stream state - stream_.state = STREAM_STOPPED; - - if ( errorText_.empty() ) - return; - else - error( errorType ); -} - -//******************** End of __WINDOWS_WASAPI__ *********************// -#endif - - -#if defined(__WINDOWS_DS__) // Windows DirectSound API - -// Modified by Robin Davies, October 2005 -// - Improvements to DirectX pointer chasing. -// - Bug fix for non-power-of-two Asio granularity used by Edirol PCR-A30. -// - Auto-call CoInitialize for DSOUND and ASIO platforms. -// Various revisions for RtAudio 4.0 by Gary Scavone, April 2007 -// Changed device query structure for RtAudio 4.0.7, January 2010 - -#include <dsound.h> -#include <assert.h> -#include <algorithm> - -#if defined(__MINGW32__) - // missing from latest mingw winapi -#define WAVE_FORMAT_96M08 0x00010000 /* 96 kHz, Mono, 8-bit */ -#define WAVE_FORMAT_96S08 0x00020000 /* 96 kHz, Stereo, 8-bit */ -#define WAVE_FORMAT_96M16 0x00040000 /* 96 kHz, Mono, 16-bit */ -#define WAVE_FORMAT_96S16 0x00080000 /* 96 kHz, Stereo, 16-bit */ -#endif - -#define MINIMUM_DEVICE_BUFFER_SIZE 32768 - -#ifdef _MSC_VER // if Microsoft Visual C++ -#pragma comment( lib, "winmm.lib" ) // then, auto-link winmm.lib. Otherwise, it has to be added manually. -#endif - -static inline DWORD dsPointerBetween( DWORD pointer, DWORD laterPointer, DWORD earlierPointer, DWORD bufferSize ) -{ - if ( pointer > bufferSize ) pointer -= bufferSize; - if ( laterPointer < earlierPointer ) laterPointer += bufferSize; - if ( pointer < earlierPointer ) pointer += bufferSize; - return pointer >= earlierPointer && pointer < laterPointer; -} - -// A structure to hold various information related to the DirectSound -// API implementation. -struct DsHandle { - unsigned int drainCounter; // Tracks callback counts when draining - bool internalDrain; // Indicates if stop is initiated from callback or not. - void *id[2]; - void *buffer[2]; - bool xrun[2]; - UINT bufferPointer[2]; - DWORD dsBufferSize[2]; - DWORD dsPointerLeadTime[2]; // the number of bytes ahead of the safe pointer to lead by. - HANDLE condition; - - DsHandle() - :drainCounter(0), internalDrain(false) { id[0] = 0; id[1] = 0; buffer[0] = 0; buffer[1] = 0; xrun[0] = false; xrun[1] = false; bufferPointer[0] = 0; bufferPointer[1] = 0; } -}; - -// Declarations for utility functions, callbacks, and structures -// specific to the DirectSound implementation. -static BOOL CALLBACK deviceQueryCallback( LPGUID lpguid, - LPCTSTR description, - LPCTSTR module, - LPVOID lpContext ); - -static const char* getErrorString( int code ); - -static unsigned __stdcall callbackHandler( void *ptr ); - -struct DsDevice { - LPGUID id[2]; - bool validId[2]; - bool found; - std::string name; - - DsDevice() - : found(false) { validId[0] = false; validId[1] = false; } -}; - -struct DsProbeData { - bool isInput; - std::vector<struct DsDevice>* dsDevices; -}; - -RtApiDs :: RtApiDs() -{ - // Dsound will run both-threaded. If CoInitialize fails, then just - // accept whatever the mainline chose for a threading model. - coInitialized_ = false; - HRESULT hr = CoInitialize( NULL ); - if ( !FAILED( hr ) ) coInitialized_ = true; -} - -RtApiDs :: ~RtApiDs() -{ - if ( coInitialized_ ) CoUninitialize(); // balanced call. - if ( stream_.state != STREAM_CLOSED ) closeStream(); -} - -// The DirectSound default output is always the first device. -unsigned int RtApiDs :: getDefaultOutputDevice( void ) -{ - return 0; -} - -// The DirectSound default input is always the first input device, -// which is the first capture device enumerated. -unsigned int RtApiDs :: getDefaultInputDevice( void ) -{ - return 0; -} - -unsigned int RtApiDs :: getDeviceCount( void ) -{ - // Set query flag for previously found devices to false, so that we - // can check for any devices that have disappeared. - for ( unsigned int i=0; i<dsDevices.size(); i++ ) - dsDevices[i].found = false; - - // Query DirectSound devices. - struct DsProbeData probeInfo; - probeInfo.isInput = false; - probeInfo.dsDevices = &dsDevices; - HRESULT result = DirectSoundEnumerate( (LPDSENUMCALLBACK) deviceQueryCallback, &probeInfo ); - if ( FAILED( result ) ) { - errorStream_ << "RtApiDs::getDeviceCount: error (" << getErrorString( result ) << ") enumerating output devices!"; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - } - - // Query DirectSoundCapture devices. - probeInfo.isInput = true; - result = DirectSoundCaptureEnumerate( (LPDSENUMCALLBACK) deviceQueryCallback, &probeInfo ); - if ( FAILED( result ) ) { - errorStream_ << "RtApiDs::getDeviceCount: error (" << getErrorString( result ) << ") enumerating input devices!"; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - } - - // Clean out any devices that may have disappeared (code update submitted by Eli Zehngut). - for ( unsigned int i=0; i<dsDevices.size(); ) { - if ( dsDevices[i].found == false ) dsDevices.erase( dsDevices.begin() + i ); - else i++; - } - - return static_cast<unsigned int>(dsDevices.size()); -} - -RtAudio::DeviceInfo RtApiDs :: getDeviceInfo( unsigned int device ) -{ - RtAudio::DeviceInfo info; - info.probed = false; - - if ( dsDevices.size() == 0 ) { - // Force a query of all devices - getDeviceCount(); - if ( dsDevices.size() == 0 ) { - errorText_ = "RtApiDs::getDeviceInfo: no devices found!"; - error( RtAudioError::INVALID_USE ); - return info; - } - } - - if ( device >= dsDevices.size() ) { - errorText_ = "RtApiDs::getDeviceInfo: device ID is invalid!"; - error( RtAudioError::INVALID_USE ); - return info; - } - - HRESULT result; - if ( dsDevices[ device ].validId[0] == false ) goto probeInput; - - LPDIRECTSOUND output; - DSCAPS outCaps; - result = DirectSoundCreate( dsDevices[ device ].id[0], &output, NULL ); - if ( FAILED( result ) ) { - errorStream_ << "RtApiDs::getDeviceInfo: error (" << getErrorString( result ) << ") opening output device (" << dsDevices[ device ].name << ")!"; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - goto probeInput; - } - - outCaps.dwSize = sizeof( outCaps ); - result = output->GetCaps( &outCaps ); - if ( FAILED( result ) ) { - output->Release(); - errorStream_ << "RtApiDs::getDeviceInfo: error (" << getErrorString( result ) << ") getting capabilities!"; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - goto probeInput; - } - - // Get output channel information. - info.outputChannels = ( outCaps.dwFlags & DSCAPS_PRIMARYSTEREO ) ? 2 : 1; - - // Get sample rate information. - info.sampleRates.clear(); - for ( unsigned int k=0; k<MAX_SAMPLE_RATES; k++ ) { - if ( SAMPLE_RATES[k] >= (unsigned int) outCaps.dwMinSecondarySampleRate && - SAMPLE_RATES[k] <= (unsigned int) outCaps.dwMaxSecondarySampleRate ) { - info.sampleRates.push_back( SAMPLE_RATES[k] ); - - if ( !info.preferredSampleRate || ( SAMPLE_RATES[k] <= 48000 && SAMPLE_RATES[k] > info.preferredSampleRate ) ) - info.preferredSampleRate = SAMPLE_RATES[k]; - } - } - - // Get format information. - if ( outCaps.dwFlags & DSCAPS_PRIMARY16BIT ) info.nativeFormats |= RTAUDIO_SINT16; - if ( outCaps.dwFlags & DSCAPS_PRIMARY8BIT ) info.nativeFormats |= RTAUDIO_SINT8; - - output->Release(); - - if ( getDefaultOutputDevice() == device ) - info.isDefaultOutput = true; - - if ( dsDevices[ device ].validId[1] == false ) { - info.name = dsDevices[ device ].name; - info.probed = true; - return info; - } - - probeInput: - - LPDIRECTSOUNDCAPTURE input; - result = DirectSoundCaptureCreate( dsDevices[ device ].id[1], &input, NULL ); - if ( FAILED( result ) ) { - errorStream_ << "RtApiDs::getDeviceInfo: error (" << getErrorString( result ) << ") opening input device (" << dsDevices[ device ].name << ")!"; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - return info; - } - - DSCCAPS inCaps; - inCaps.dwSize = sizeof( inCaps ); - result = input->GetCaps( &inCaps ); - if ( FAILED( result ) ) { - input->Release(); - errorStream_ << "RtApiDs::getDeviceInfo: error (" << getErrorString( result ) << ") getting object capabilities (" << dsDevices[ device ].name << ")!"; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - return info; - } - - // Get input channel information. - info.inputChannels = inCaps.dwChannels; - - // Get sample rate and format information. - std::vector<unsigned int> rates; - if ( inCaps.dwChannels >= 2 ) { - if ( inCaps.dwFormats & WAVE_FORMAT_1S16 ) info.nativeFormats |= RTAUDIO_SINT16; - if ( inCaps.dwFormats & WAVE_FORMAT_2S16 ) info.nativeFormats |= RTAUDIO_SINT16; - if ( inCaps.dwFormats & WAVE_FORMAT_4S16 ) info.nativeFormats |= RTAUDIO_SINT16; - if ( inCaps.dwFormats & WAVE_FORMAT_96S16 ) info.nativeFormats |= RTAUDIO_SINT16; - if ( inCaps.dwFormats & WAVE_FORMAT_1S08 ) info.nativeFormats |= RTAUDIO_SINT8; - if ( inCaps.dwFormats & WAVE_FORMAT_2S08 ) info.nativeFormats |= RTAUDIO_SINT8; - if ( inCaps.dwFormats & WAVE_FORMAT_4S08 ) info.nativeFormats |= RTAUDIO_SINT8; - if ( inCaps.dwFormats & WAVE_FORMAT_96S08 ) info.nativeFormats |= RTAUDIO_SINT8; - - if ( info.nativeFormats & RTAUDIO_SINT16 ) { - if ( inCaps.dwFormats & WAVE_FORMAT_1S16 ) rates.push_back( 11025 ); - if ( inCaps.dwFormats & WAVE_FORMAT_2S16 ) rates.push_back( 22050 ); - if ( inCaps.dwFormats & WAVE_FORMAT_4S16 ) rates.push_back( 44100 ); - if ( inCaps.dwFormats & WAVE_FORMAT_96S16 ) rates.push_back( 96000 ); - } - else if ( info.nativeFormats & RTAUDIO_SINT8 ) { - if ( inCaps.dwFormats & WAVE_FORMAT_1S08 ) rates.push_back( 11025 ); - if ( inCaps.dwFormats & WAVE_FORMAT_2S08 ) rates.push_back( 22050 ); - if ( inCaps.dwFormats & WAVE_FORMAT_4S08 ) rates.push_back( 44100 ); - if ( inCaps.dwFormats & WAVE_FORMAT_96S08 ) rates.push_back( 96000 ); - } - } - else if ( inCaps.dwChannels == 1 ) { - if ( inCaps.dwFormats & WAVE_FORMAT_1M16 ) info.nativeFormats |= RTAUDIO_SINT16; - if ( inCaps.dwFormats & WAVE_FORMAT_2M16 ) info.nativeFormats |= RTAUDIO_SINT16; - if ( inCaps.dwFormats & WAVE_FORMAT_4M16 ) info.nativeFormats |= RTAUDIO_SINT16; - if ( inCaps.dwFormats & WAVE_FORMAT_96M16 ) info.nativeFormats |= RTAUDIO_SINT16; - if ( inCaps.dwFormats & WAVE_FORMAT_1M08 ) info.nativeFormats |= RTAUDIO_SINT8; - if ( inCaps.dwFormats & WAVE_FORMAT_2M08 ) info.nativeFormats |= RTAUDIO_SINT8; - if ( inCaps.dwFormats & WAVE_FORMAT_4M08 ) info.nativeFormats |= RTAUDIO_SINT8; - if ( inCaps.dwFormats & WAVE_FORMAT_96M08 ) info.nativeFormats |= RTAUDIO_SINT8; - - if ( info.nativeFormats & RTAUDIO_SINT16 ) { - if ( inCaps.dwFormats & WAVE_FORMAT_1M16 ) rates.push_back( 11025 ); - if ( inCaps.dwFormats & WAVE_FORMAT_2M16 ) rates.push_back( 22050 ); - if ( inCaps.dwFormats & WAVE_FORMAT_4M16 ) rates.push_back( 44100 ); - if ( inCaps.dwFormats & WAVE_FORMAT_96M16 ) rates.push_back( 96000 ); - } - else if ( info.nativeFormats & RTAUDIO_SINT8 ) { - if ( inCaps.dwFormats & WAVE_FORMAT_1M08 ) rates.push_back( 11025 ); - if ( inCaps.dwFormats & WAVE_FORMAT_2M08 ) rates.push_back( 22050 ); - if ( inCaps.dwFormats & WAVE_FORMAT_4M08 ) rates.push_back( 44100 ); - if ( inCaps.dwFormats & WAVE_FORMAT_96M08 ) rates.push_back( 96000 ); - } - } - else info.inputChannels = 0; // technically, this would be an error - - input->Release(); - - if ( info.inputChannels == 0 ) return info; - - // Copy the supported rates to the info structure but avoid duplication. - bool found; - for ( unsigned int i=0; i<rates.size(); i++ ) { - found = false; - for ( unsigned int j=0; j<info.sampleRates.size(); j++ ) { - if ( rates[i] == info.sampleRates[j] ) { - found = true; - break; - } - } - if ( found == false ) info.sampleRates.push_back( rates[i] ); - } - std::sort( info.sampleRates.begin(), info.sampleRates.end() ); - - // If device opens for both playback and capture, we determine the channels. - if ( info.outputChannels > 0 && info.inputChannels > 0 ) - info.duplexChannels = (info.outputChannels > info.inputChannels) ? info.inputChannels : info.outputChannels; - - if ( device == 0 ) info.isDefaultInput = true; - - // Copy name and return. - info.name = dsDevices[ device ].name; - info.probed = true; - return info; -} - -bool RtApiDs :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, - unsigned int firstChannel, unsigned int sampleRate, - RtAudioFormat format, unsigned int *bufferSize, - RtAudio::StreamOptions *options ) -{ - if ( channels + firstChannel > 2 ) { - errorText_ = "RtApiDs::probeDeviceOpen: DirectSound does not support more than 2 channels per device."; - return FAILURE; - } - - size_t nDevices = dsDevices.size(); - if ( nDevices == 0 ) { - // This should not happen because a check is made before this function is called. - errorText_ = "RtApiDs::probeDeviceOpen: no devices found!"; - return FAILURE; - } - - if ( device >= nDevices ) { - // This should not happen because a check is made before this function is called. - errorText_ = "RtApiDs::probeDeviceOpen: device ID is invalid!"; - return FAILURE; - } - - if ( mode == OUTPUT ) { - if ( dsDevices[ device ].validId[0] == false ) { - errorStream_ << "RtApiDs::probeDeviceOpen: device (" << device << ") does not support output!"; - errorText_ = errorStream_.str(); - return FAILURE; - } - } - else { // mode == INPUT - if ( dsDevices[ device ].validId[1] == false ) { - errorStream_ << "RtApiDs::probeDeviceOpen: device (" << device << ") does not support input!"; - errorText_ = errorStream_.str(); - return FAILURE; - } - } - - // According to a note in PortAudio, using GetDesktopWindow() - // instead of GetForegroundWindow() is supposed to avoid problems - // that occur when the application's window is not the foreground - // window. Also, if the application window closes before the - // DirectSound buffer, DirectSound can crash. In the past, I had - // problems when using GetDesktopWindow() but it seems fine now - // (January 2010). I'll leave it commented here. - // HWND hWnd = GetForegroundWindow(); - HWND hWnd = GetDesktopWindow(); - - // Check the numberOfBuffers parameter and limit the lowest value to - // two. This is a judgement call and a value of two is probably too - // low for capture, but it should work for playback. - int nBuffers = 0; - if ( options ) nBuffers = options->numberOfBuffers; - if ( options && options->flags & RTAUDIO_MINIMIZE_LATENCY ) nBuffers = 2; - if ( nBuffers < 2 ) nBuffers = 3; - - // Check the lower range of the user-specified buffer size and set - // (arbitrarily) to a lower bound of 32. - if ( *bufferSize < 32 ) *bufferSize = 32; - - // Create the wave format structure. The data format setting will - // be determined later. - WAVEFORMATEX waveFormat; - ZeroMemory( &waveFormat, sizeof(WAVEFORMATEX) ); - waveFormat.wFormatTag = WAVE_FORMAT_PCM; - waveFormat.nChannels = channels + firstChannel; - waveFormat.nSamplesPerSec = (unsigned long) sampleRate; - - // Determine the device buffer size. By default, we'll use the value - // defined above (32K), but we will grow it to make allowances for - // very large software buffer sizes. - DWORD dsBufferSize = MINIMUM_DEVICE_BUFFER_SIZE; - DWORD dsPointerLeadTime = 0; - - void *ohandle = 0, *bhandle = 0; - HRESULT result; - if ( mode == OUTPUT ) { - - LPDIRECTSOUND output; - result = DirectSoundCreate( dsDevices[ device ].id[0], &output, NULL ); - if ( FAILED( result ) ) { - errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") opening output device (" << dsDevices[ device ].name << ")!"; - errorText_ = errorStream_.str(); - return FAILURE; - } - - DSCAPS outCaps; - outCaps.dwSize = sizeof( outCaps ); - result = output->GetCaps( &outCaps ); - if ( FAILED( result ) ) { - output->Release(); - errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") getting capabilities (" << dsDevices[ device ].name << ")!"; - errorText_ = errorStream_.str(); - return FAILURE; - } - - // Check channel information. - if ( channels + firstChannel == 2 && !( outCaps.dwFlags & DSCAPS_PRIMARYSTEREO ) ) { - errorStream_ << "RtApiDs::getDeviceInfo: the output device (" << dsDevices[ device ].name << ") does not support stereo playback."; - errorText_ = errorStream_.str(); - return FAILURE; - } - - // Check format information. Use 16-bit format unless not - // supported or user requests 8-bit. - if ( outCaps.dwFlags & DSCAPS_PRIMARY16BIT && - !( format == RTAUDIO_SINT8 && outCaps.dwFlags & DSCAPS_PRIMARY8BIT ) ) { - waveFormat.wBitsPerSample = 16; - stream_.deviceFormat[mode] = RTAUDIO_SINT16; - } - else { - waveFormat.wBitsPerSample = 8; - stream_.deviceFormat[mode] = RTAUDIO_SINT8; - } - stream_.userFormat = format; - - // Update wave format structure and buffer information. - waveFormat.nBlockAlign = waveFormat.nChannels * waveFormat.wBitsPerSample / 8; - waveFormat.nAvgBytesPerSec = waveFormat.nSamplesPerSec * waveFormat.nBlockAlign; - dsPointerLeadTime = nBuffers * (*bufferSize) * (waveFormat.wBitsPerSample / 8) * channels; - - // If the user wants an even bigger buffer, increase the device buffer size accordingly. - while ( dsPointerLeadTime * 2U > dsBufferSize ) - dsBufferSize *= 2; - - // Set cooperative level to DSSCL_EXCLUSIVE ... sound stops when window focus changes. - // result = output->SetCooperativeLevel( hWnd, DSSCL_EXCLUSIVE ); - // Set cooperative level to DSSCL_PRIORITY ... sound remains when window focus changes. - result = output->SetCooperativeLevel( hWnd, DSSCL_PRIORITY ); - if ( FAILED( result ) ) { - output->Release(); - errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") setting cooperative level (" << dsDevices[ device ].name << ")!"; - errorText_ = errorStream_.str(); - return FAILURE; - } - - // Even though we will write to the secondary buffer, we need to - // access the primary buffer to set the correct output format - // (since the default is 8-bit, 22 kHz!). Setup the DS primary - // buffer description. - DSBUFFERDESC bufferDescription; - ZeroMemory( &bufferDescription, sizeof( DSBUFFERDESC ) ); - bufferDescription.dwSize = sizeof( DSBUFFERDESC ); - bufferDescription.dwFlags = DSBCAPS_PRIMARYBUFFER; - - // Obtain the primary buffer - LPDIRECTSOUNDBUFFER buffer; - result = output->CreateSoundBuffer( &bufferDescription, &buffer, NULL ); - if ( FAILED( result ) ) { - output->Release(); - errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") accessing primary buffer (" << dsDevices[ device ].name << ")!"; - errorText_ = errorStream_.str(); - return FAILURE; - } - - // Set the primary DS buffer sound format. - result = buffer->SetFormat( &waveFormat ); - if ( FAILED( result ) ) { - output->Release(); - errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") setting primary buffer format (" << dsDevices[ device ].name << ")!"; - errorText_ = errorStream_.str(); - return FAILURE; - } - - // Setup the secondary DS buffer description. - ZeroMemory( &bufferDescription, sizeof( DSBUFFERDESC ) ); - bufferDescription.dwSize = sizeof( DSBUFFERDESC ); - bufferDescription.dwFlags = ( DSBCAPS_STICKYFOCUS | - DSBCAPS_GLOBALFOCUS | - DSBCAPS_GETCURRENTPOSITION2 | - DSBCAPS_LOCHARDWARE ); // Force hardware mixing - bufferDescription.dwBufferBytes = dsBufferSize; - bufferDescription.lpwfxFormat = &waveFormat; - - // Try to create the secondary DS buffer. If that doesn't work, - // try to use software mixing. Otherwise, there's a problem. - result = output->CreateSoundBuffer( &bufferDescription, &buffer, NULL ); - if ( FAILED( result ) ) { - bufferDescription.dwFlags = ( DSBCAPS_STICKYFOCUS | - DSBCAPS_GLOBALFOCUS | - DSBCAPS_GETCURRENTPOSITION2 | - DSBCAPS_LOCSOFTWARE ); // Force software mixing - result = output->CreateSoundBuffer( &bufferDescription, &buffer, NULL ); - if ( FAILED( result ) ) { - output->Release(); - errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") creating secondary buffer (" << dsDevices[ device ].name << ")!"; - errorText_ = errorStream_.str(); - return FAILURE; - } - } - - // Get the buffer size ... might be different from what we specified. - DSBCAPS dsbcaps; - dsbcaps.dwSize = sizeof( DSBCAPS ); - result = buffer->GetCaps( &dsbcaps ); - if ( FAILED( result ) ) { - output->Release(); - buffer->Release(); - errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") getting buffer settings (" << dsDevices[ device ].name << ")!"; - errorText_ = errorStream_.str(); - return FAILURE; - } - - dsBufferSize = dsbcaps.dwBufferBytes; - - // Lock the DS buffer - LPVOID audioPtr; - DWORD dataLen; - result = buffer->Lock( 0, dsBufferSize, &audioPtr, &dataLen, NULL, NULL, 0 ); - if ( FAILED( result ) ) { - output->Release(); - buffer->Release(); - errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") locking buffer (" << dsDevices[ device ].name << ")!"; - errorText_ = errorStream_.str(); - return FAILURE; - } - - // Zero the DS buffer - ZeroMemory( audioPtr, dataLen ); - - // Unlock the DS buffer - result = buffer->Unlock( audioPtr, dataLen, NULL, 0 ); - if ( FAILED( result ) ) { - output->Release(); - buffer->Release(); - errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") unlocking buffer (" << dsDevices[ device ].name << ")!"; - errorText_ = errorStream_.str(); - return FAILURE; - } - - ohandle = (void *) output; - bhandle = (void *) buffer; - } - - if ( mode == INPUT ) { - - LPDIRECTSOUNDCAPTURE input; - result = DirectSoundCaptureCreate( dsDevices[ device ].id[1], &input, NULL ); - if ( FAILED( result ) ) { - errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") opening input device (" << dsDevices[ device ].name << ")!"; - errorText_ = errorStream_.str(); - return FAILURE; - } - - DSCCAPS inCaps; - inCaps.dwSize = sizeof( inCaps ); - result = input->GetCaps( &inCaps ); - if ( FAILED( result ) ) { - input->Release(); - errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") getting input capabilities (" << dsDevices[ device ].name << ")!"; - errorText_ = errorStream_.str(); - return FAILURE; - } - - // Check channel information. - if ( inCaps.dwChannels < channels + firstChannel ) { - errorText_ = "RtApiDs::getDeviceInfo: the input device does not support requested input channels."; - return FAILURE; - } - - // Check format information. Use 16-bit format unless user - // requests 8-bit. - DWORD deviceFormats; - if ( channels + firstChannel == 2 ) { - deviceFormats = WAVE_FORMAT_1S08 | WAVE_FORMAT_2S08 | WAVE_FORMAT_4S08 | WAVE_FORMAT_96S08; - if ( format == RTAUDIO_SINT8 && inCaps.dwFormats & deviceFormats ) { - waveFormat.wBitsPerSample = 8; - stream_.deviceFormat[mode] = RTAUDIO_SINT8; - } - else { // assume 16-bit is supported - waveFormat.wBitsPerSample = 16; - stream_.deviceFormat[mode] = RTAUDIO_SINT16; - } - } - else { // channel == 1 - deviceFormats = WAVE_FORMAT_1M08 | WAVE_FORMAT_2M08 | WAVE_FORMAT_4M08 | WAVE_FORMAT_96M08; - if ( format == RTAUDIO_SINT8 && inCaps.dwFormats & deviceFormats ) { - waveFormat.wBitsPerSample = 8; - stream_.deviceFormat[mode] = RTAUDIO_SINT8; - } - else { // assume 16-bit is supported - waveFormat.wBitsPerSample = 16; - stream_.deviceFormat[mode] = RTAUDIO_SINT16; - } - } - stream_.userFormat = format; - - // Update wave format structure and buffer information. - waveFormat.nBlockAlign = waveFormat.nChannels * waveFormat.wBitsPerSample / 8; - waveFormat.nAvgBytesPerSec = waveFormat.nSamplesPerSec * waveFormat.nBlockAlign; - dsPointerLeadTime = nBuffers * (*bufferSize) * (waveFormat.wBitsPerSample / 8) * channels; - - // If the user wants an even bigger buffer, increase the device buffer size accordingly. - while ( dsPointerLeadTime * 2U > dsBufferSize ) - dsBufferSize *= 2; - - // Setup the secondary DS buffer description. - DSCBUFFERDESC bufferDescription; - ZeroMemory( &bufferDescription, sizeof( DSCBUFFERDESC ) ); - bufferDescription.dwSize = sizeof( DSCBUFFERDESC ); - bufferDescription.dwFlags = 0; - bufferDescription.dwReserved = 0; - bufferDescription.dwBufferBytes = dsBufferSize; - bufferDescription.lpwfxFormat = &waveFormat; - - // Create the capture buffer. - LPDIRECTSOUNDCAPTUREBUFFER buffer; - result = input->CreateCaptureBuffer( &bufferDescription, &buffer, NULL ); - if ( FAILED( result ) ) { - input->Release(); - errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") creating input buffer (" << dsDevices[ device ].name << ")!"; - errorText_ = errorStream_.str(); - return FAILURE; - } - - // Get the buffer size ... might be different from what we specified. - DSCBCAPS dscbcaps; - dscbcaps.dwSize = sizeof( DSCBCAPS ); - result = buffer->GetCaps( &dscbcaps ); - if ( FAILED( result ) ) { - input->Release(); - buffer->Release(); - errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") getting buffer settings (" << dsDevices[ device ].name << ")!"; - errorText_ = errorStream_.str(); - return FAILURE; - } - - dsBufferSize = dscbcaps.dwBufferBytes; - - // NOTE: We could have a problem here if this is a duplex stream - // and the play and capture hardware buffer sizes are different - // (I'm actually not sure if that is a problem or not). - // Currently, we are not verifying that. - - // Lock the capture buffer - LPVOID audioPtr; - DWORD dataLen; - result = buffer->Lock( 0, dsBufferSize, &audioPtr, &dataLen, NULL, NULL, 0 ); - if ( FAILED( result ) ) { - input->Release(); - buffer->Release(); - errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") locking input buffer (" << dsDevices[ device ].name << ")!"; - errorText_ = errorStream_.str(); - return FAILURE; - } - - // Zero the buffer - ZeroMemory( audioPtr, dataLen ); - - // Unlock the buffer - result = buffer->Unlock( audioPtr, dataLen, NULL, 0 ); - if ( FAILED( result ) ) { - input->Release(); - buffer->Release(); - errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") unlocking input buffer (" << dsDevices[ device ].name << ")!"; - errorText_ = errorStream_.str(); - return FAILURE; - } - - ohandle = (void *) input; - bhandle = (void *) buffer; - } - - // Set various stream parameters - DsHandle *handle = 0; - stream_.nDeviceChannels[mode] = channels + firstChannel; - stream_.nUserChannels[mode] = channels; - stream_.bufferSize = *bufferSize; - stream_.channelOffset[mode] = firstChannel; - stream_.deviceInterleaved[mode] = true; - if ( options && options->flags & RTAUDIO_NONINTERLEAVED ) stream_.userInterleaved = false; - else stream_.userInterleaved = true; - - // Set flag for buffer conversion - stream_.doConvertBuffer[mode] = false; - if (stream_.nUserChannels[mode] != stream_.nDeviceChannels[mode]) - stream_.doConvertBuffer[mode] = true; - if (stream_.userFormat != stream_.deviceFormat[mode]) - stream_.doConvertBuffer[mode] = true; - if ( stream_.userInterleaved != stream_.deviceInterleaved[mode] && - stream_.nUserChannels[mode] > 1 ) - stream_.doConvertBuffer[mode] = true; - - // Allocate necessary internal buffers - long bufferBytes = stream_.nUserChannels[mode] * *bufferSize * formatBytes( stream_.userFormat ); - stream_.userBuffer[mode] = (char *) calloc( bufferBytes, 1 ); - if ( stream_.userBuffer[mode] == NULL ) { - errorText_ = "RtApiDs::probeDeviceOpen: error allocating user buffer memory."; - goto error; - } - - if ( stream_.doConvertBuffer[mode] ) { - - bool makeBuffer = true; - bufferBytes = stream_.nDeviceChannels[mode] * formatBytes( stream_.deviceFormat[mode] ); - if ( mode == INPUT ) { - if ( stream_.mode == OUTPUT && stream_.deviceBuffer ) { - unsigned long bytesOut = stream_.nDeviceChannels[0] * formatBytes( stream_.deviceFormat[0] ); - if ( bufferBytes <= (long) bytesOut ) makeBuffer = false; - } - } - - if ( makeBuffer ) { - bufferBytes *= *bufferSize; - if ( stream_.deviceBuffer ) free( stream_.deviceBuffer ); - stream_.deviceBuffer = (char *) calloc( bufferBytes, 1 ); - if ( stream_.deviceBuffer == NULL ) { - errorText_ = "RtApiDs::probeDeviceOpen: error allocating device buffer memory."; - goto error; - } - } - } - - // Allocate our DsHandle structures for the stream. - if ( stream_.apiHandle == 0 ) { - try { - handle = new DsHandle; - } - catch ( std::bad_alloc& ) { - errorText_ = "RtApiDs::probeDeviceOpen: error allocating AsioHandle memory."; - goto error; - } - - // Create a manual-reset event. - handle->condition = CreateEvent( NULL, // no security - TRUE, // manual-reset - FALSE, // non-signaled initially - NULL ); // unnamed - stream_.apiHandle = (void *) handle; - } - else - handle = (DsHandle *) stream_.apiHandle; - handle->id[mode] = ohandle; - handle->buffer[mode] = bhandle; - handle->dsBufferSize[mode] = dsBufferSize; - handle->dsPointerLeadTime[mode] = dsPointerLeadTime; - - stream_.device[mode] = device; - stream_.state = STREAM_STOPPED; - if ( stream_.mode == OUTPUT && mode == INPUT ) - // We had already set up an output stream. - stream_.mode = DUPLEX; - else - stream_.mode = mode; - stream_.nBuffers = nBuffers; - stream_.sampleRate = sampleRate; - - // Setup the buffer conversion information structure. - if ( stream_.doConvertBuffer[mode] ) setConvertInfo( mode, firstChannel ); - - // Setup the callback thread. - if ( stream_.callbackInfo.isRunning == false ) { - unsigned threadId; - stream_.callbackInfo.isRunning = true; - stream_.callbackInfo.object = (void *) this; - stream_.callbackInfo.thread = _beginthreadex( NULL, 0, &callbackHandler, - &stream_.callbackInfo, 0, &threadId ); - if ( stream_.callbackInfo.thread == 0 ) { - errorText_ = "RtApiDs::probeDeviceOpen: error creating callback thread!"; - goto error; - } - - // Boost DS thread priority - SetThreadPriority( (HANDLE) stream_.callbackInfo.thread, THREAD_PRIORITY_HIGHEST ); - } - return SUCCESS; - - error: - if ( handle ) { - if ( handle->buffer[0] ) { // the object pointer can be NULL and valid - LPDIRECTSOUND object = (LPDIRECTSOUND) handle->id[0]; - LPDIRECTSOUNDBUFFER buffer = (LPDIRECTSOUNDBUFFER) handle->buffer[0]; - if ( buffer ) buffer->Release(); - object->Release(); - } - if ( handle->buffer[1] ) { - LPDIRECTSOUNDCAPTURE object = (LPDIRECTSOUNDCAPTURE) handle->id[1]; - LPDIRECTSOUNDCAPTUREBUFFER buffer = (LPDIRECTSOUNDCAPTUREBUFFER) handle->buffer[1]; - if ( buffer ) buffer->Release(); - object->Release(); - } - CloseHandle( handle->condition ); - delete handle; - stream_.apiHandle = 0; - } - - for ( int i=0; i<2; i++ ) { - if ( stream_.userBuffer[i] ) { - free( stream_.userBuffer[i] ); - stream_.userBuffer[i] = 0; - } - } - - if ( stream_.deviceBuffer ) { - free( stream_.deviceBuffer ); - stream_.deviceBuffer = 0; - } - - stream_.state = STREAM_CLOSED; - return FAILURE; -} - -void RtApiDs :: closeStream() -{ - if ( stream_.state == STREAM_CLOSED ) { - errorText_ = "RtApiDs::closeStream(): no open stream to close!"; - error( RtAudioError::WARNING ); - return; - } - - // Stop the callback thread. - stream_.callbackInfo.isRunning = false; - WaitForSingleObject( (HANDLE) stream_.callbackInfo.thread, INFINITE ); - CloseHandle( (HANDLE) stream_.callbackInfo.thread ); - - DsHandle *handle = (DsHandle *) stream_.apiHandle; - if ( handle ) { - if ( handle->buffer[0] ) { // the object pointer can be NULL and valid - LPDIRECTSOUND object = (LPDIRECTSOUND) handle->id[0]; - LPDIRECTSOUNDBUFFER buffer = (LPDIRECTSOUNDBUFFER) handle->buffer[0]; - if ( buffer ) { - buffer->Stop(); - buffer->Release(); - } - object->Release(); - } - if ( handle->buffer[1] ) { - LPDIRECTSOUNDCAPTURE object = (LPDIRECTSOUNDCAPTURE) handle->id[1]; - LPDIRECTSOUNDCAPTUREBUFFER buffer = (LPDIRECTSOUNDCAPTUREBUFFER) handle->buffer[1]; - if ( buffer ) { - buffer->Stop(); - buffer->Release(); - } - object->Release(); - } - CloseHandle( handle->condition ); - delete handle; - stream_.apiHandle = 0; - } - - for ( int i=0; i<2; i++ ) { - if ( stream_.userBuffer[i] ) { - free( stream_.userBuffer[i] ); - stream_.userBuffer[i] = 0; - } - } - - if ( stream_.deviceBuffer ) { - free( stream_.deviceBuffer ); - stream_.deviceBuffer = 0; - } - - stream_.mode = UNINITIALIZED; - stream_.state = STREAM_CLOSED; -} - -void RtApiDs :: startStream() -{ - verifyStream(); - if ( stream_.state == STREAM_RUNNING ) { - errorText_ = "RtApiDs::startStream(): the stream is already running!"; - error( RtAudioError::WARNING ); - return; - } - - DsHandle *handle = (DsHandle *) stream_.apiHandle; - - // Increase scheduler frequency on lesser windows (a side-effect of - // increasing timer accuracy). On greater windows (Win2K or later), - // this is already in effect. - timeBeginPeriod( 1 ); - - buffersRolling = false; - duplexPrerollBytes = 0; - - if ( stream_.mode == DUPLEX ) { - // 0.5 seconds of silence in DUPLEX mode while the devices spin up and synchronize. - duplexPrerollBytes = (int) ( 0.5 * stream_.sampleRate * formatBytes( stream_.deviceFormat[1] ) * stream_.nDeviceChannels[1] ); - } - - HRESULT result = 0; - if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) { - - LPDIRECTSOUNDBUFFER buffer = (LPDIRECTSOUNDBUFFER) handle->buffer[0]; - result = buffer->Play( 0, 0, DSBPLAY_LOOPING ); - if ( FAILED( result ) ) { - errorStream_ << "RtApiDs::startStream: error (" << getErrorString( result ) << ") starting output buffer!"; - errorText_ = errorStream_.str(); - goto unlock; - } - } - - if ( stream_.mode == INPUT || stream_.mode == DUPLEX ) { - - LPDIRECTSOUNDCAPTUREBUFFER buffer = (LPDIRECTSOUNDCAPTUREBUFFER) handle->buffer[1]; - result = buffer->Start( DSCBSTART_LOOPING ); - if ( FAILED( result ) ) { - errorStream_ << "RtApiDs::startStream: error (" << getErrorString( result ) << ") starting input buffer!"; - errorText_ = errorStream_.str(); - goto unlock; - } - } - - handle->drainCounter = 0; - handle->internalDrain = false; - ResetEvent( handle->condition ); - stream_.state = STREAM_RUNNING; - - unlock: - if ( FAILED( result ) ) error( RtAudioError::SYSTEM_ERROR ); -} - -void RtApiDs :: stopStream() -{ - verifyStream(); - if ( stream_.state == STREAM_STOPPED ) { - errorText_ = "RtApiDs::stopStream(): the stream is already stopped!"; - error( RtAudioError::WARNING ); - return; - } - - HRESULT result = 0; - LPVOID audioPtr; - DWORD dataLen; - DsHandle *handle = (DsHandle *) stream_.apiHandle; - if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) { - if ( handle->drainCounter == 0 ) { - handle->drainCounter = 2; - WaitForSingleObject( handle->condition, INFINITE ); // block until signaled - } - - stream_.state = STREAM_STOPPED; - - MUTEX_LOCK( &stream_.mutex ); - - // Stop the buffer and clear memory - LPDIRECTSOUNDBUFFER buffer = (LPDIRECTSOUNDBUFFER) handle->buffer[0]; - result = buffer->Stop(); - if ( FAILED( result ) ) { - errorStream_ << "RtApiDs::stopStream: error (" << getErrorString( result ) << ") stopping output buffer!"; - errorText_ = errorStream_.str(); - goto unlock; - } - - // Lock the buffer and clear it so that if we start to play again, - // we won't have old data playing. - result = buffer->Lock( 0, handle->dsBufferSize[0], &audioPtr, &dataLen, NULL, NULL, 0 ); - if ( FAILED( result ) ) { - errorStream_ << "RtApiDs::stopStream: error (" << getErrorString( result ) << ") locking output buffer!"; - errorText_ = errorStream_.str(); - goto unlock; - } - - // Zero the DS buffer - ZeroMemory( audioPtr, dataLen ); - - // Unlock the DS buffer - result = buffer->Unlock( audioPtr, dataLen, NULL, 0 ); - if ( FAILED( result ) ) { - errorStream_ << "RtApiDs::stopStream: error (" << getErrorString( result ) << ") unlocking output buffer!"; - errorText_ = errorStream_.str(); - goto unlock; - } - - // If we start playing again, we must begin at beginning of buffer. - handle->bufferPointer[0] = 0; - } - - if ( stream_.mode == INPUT || stream_.mode == DUPLEX ) { - LPDIRECTSOUNDCAPTUREBUFFER buffer = (LPDIRECTSOUNDCAPTUREBUFFER) handle->buffer[1]; - audioPtr = NULL; - dataLen = 0; - - stream_.state = STREAM_STOPPED; - - if ( stream_.mode != DUPLEX ) - MUTEX_LOCK( &stream_.mutex ); - - result = buffer->Stop(); - if ( FAILED( result ) ) { - errorStream_ << "RtApiDs::stopStream: error (" << getErrorString( result ) << ") stopping input buffer!"; - errorText_ = errorStream_.str(); - goto unlock; - } - - // Lock the buffer and clear it so that if we start to play again, - // we won't have old data playing. - result = buffer->Lock( 0, handle->dsBufferSize[1], &audioPtr, &dataLen, NULL, NULL, 0 ); - if ( FAILED( result ) ) { - errorStream_ << "RtApiDs::stopStream: error (" << getErrorString( result ) << ") locking input buffer!"; - errorText_ = errorStream_.str(); - goto unlock; - } - - // Zero the DS buffer - ZeroMemory( audioPtr, dataLen ); - - // Unlock the DS buffer - result = buffer->Unlock( audioPtr, dataLen, NULL, 0 ); - if ( FAILED( result ) ) { - errorStream_ << "RtApiDs::stopStream: error (" << getErrorString( result ) << ") unlocking input buffer!"; - errorText_ = errorStream_.str(); - goto unlock; - } - - // If we start recording again, we must begin at beginning of buffer. - handle->bufferPointer[1] = 0; - } - - unlock: - timeEndPeriod( 1 ); // revert to normal scheduler frequency on lesser windows. - MUTEX_UNLOCK( &stream_.mutex ); - - if ( FAILED( result ) ) error( RtAudioError::SYSTEM_ERROR ); -} - -void RtApiDs :: abortStream() -{ - verifyStream(); - if ( stream_.state == STREAM_STOPPED ) { - errorText_ = "RtApiDs::abortStream(): the stream is already stopped!"; - error( RtAudioError::WARNING ); - return; - } - - DsHandle *handle = (DsHandle *) stream_.apiHandle; - handle->drainCounter = 2; - - stopStream(); -} - -void RtApiDs :: callbackEvent() -{ - if ( stream_.state == STREAM_STOPPED || stream_.state == STREAM_STOPPING ) { - Sleep( 50 ); // sleep 50 milliseconds - return; - } - - if ( stream_.state == STREAM_CLOSED ) { - errorText_ = "RtApiDs::callbackEvent(): the stream is closed ... this shouldn't happen!"; - error( RtAudioError::WARNING ); - return; - } - - CallbackInfo *info = (CallbackInfo *) &stream_.callbackInfo; - DsHandle *handle = (DsHandle *) stream_.apiHandle; - - // Check if we were draining the stream and signal is finished. - if ( handle->drainCounter > stream_.nBuffers + 2 ) { - - stream_.state = STREAM_STOPPING; - if ( handle->internalDrain == false ) - SetEvent( handle->condition ); - else - stopStream(); - return; - } - - // Invoke user callback to get fresh output data UNLESS we are - // draining stream. - if ( handle->drainCounter == 0 ) { - RtAudioCallback callback = (RtAudioCallback) info->callback; - double streamTime = getStreamTime(); - RtAudioStreamStatus status = 0; - if ( stream_.mode != INPUT && handle->xrun[0] == true ) { - status |= RTAUDIO_OUTPUT_UNDERFLOW; - handle->xrun[0] = false; - } - if ( stream_.mode != OUTPUT && handle->xrun[1] == true ) { - status |= RTAUDIO_INPUT_OVERFLOW; - handle->xrun[1] = false; - } - int cbReturnValue = callback( stream_.userBuffer[0], stream_.userBuffer[1], - stream_.bufferSize, streamTime, status, info->userData ); - if ( cbReturnValue == 2 ) { - stream_.state = STREAM_STOPPING; - handle->drainCounter = 2; - abortStream(); - return; - } - else if ( cbReturnValue == 1 ) { - handle->drainCounter = 1; - handle->internalDrain = true; - } - } - - HRESULT result; - DWORD currentWritePointer, safeWritePointer; - DWORD currentReadPointer, safeReadPointer; - UINT nextWritePointer; - - LPVOID buffer1 = NULL; - LPVOID buffer2 = NULL; - DWORD bufferSize1 = 0; - DWORD bufferSize2 = 0; - - char *buffer; - long bufferBytes; - - MUTEX_LOCK( &stream_.mutex ); - if ( stream_.state == STREAM_STOPPED ) { - MUTEX_UNLOCK( &stream_.mutex ); - return; - } - - if ( buffersRolling == false ) { - if ( stream_.mode == DUPLEX ) { - //assert( handle->dsBufferSize[0] == handle->dsBufferSize[1] ); - - // It takes a while for the devices to get rolling. As a result, - // there's no guarantee that the capture and write device pointers - // will move in lockstep. Wait here for both devices to start - // rolling, and then set our buffer pointers accordingly. - // e.g. Crystal Drivers: the capture buffer starts up 5700 to 9600 - // bytes later than the write buffer. - - // Stub: a serious risk of having a pre-emptive scheduling round - // take place between the two GetCurrentPosition calls... but I'm - // really not sure how to solve the problem. Temporarily boost to - // Realtime priority, maybe; but I'm not sure what priority the - // DirectSound service threads run at. We *should* be roughly - // within a ms or so of correct. - - LPDIRECTSOUNDBUFFER dsWriteBuffer = (LPDIRECTSOUNDBUFFER) handle->buffer[0]; - LPDIRECTSOUNDCAPTUREBUFFER dsCaptureBuffer = (LPDIRECTSOUNDCAPTUREBUFFER) handle->buffer[1]; - - DWORD startSafeWritePointer, startSafeReadPointer; - - result = dsWriteBuffer->GetCurrentPosition( NULL, &startSafeWritePointer ); - if ( FAILED( result ) ) { - errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") getting current write position!"; - errorText_ = errorStream_.str(); - MUTEX_UNLOCK( &stream_.mutex ); - error( RtAudioError::SYSTEM_ERROR ); - return; - } - result = dsCaptureBuffer->GetCurrentPosition( NULL, &startSafeReadPointer ); - if ( FAILED( result ) ) { - errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") getting current read position!"; - errorText_ = errorStream_.str(); - MUTEX_UNLOCK( &stream_.mutex ); - error( RtAudioError::SYSTEM_ERROR ); - return; - } - while ( true ) { - result = dsWriteBuffer->GetCurrentPosition( NULL, &safeWritePointer ); - if ( FAILED( result ) ) { - errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") getting current write position!"; - errorText_ = errorStream_.str(); - MUTEX_UNLOCK( &stream_.mutex ); - error( RtAudioError::SYSTEM_ERROR ); - return; - } - result = dsCaptureBuffer->GetCurrentPosition( NULL, &safeReadPointer ); - if ( FAILED( result ) ) { - errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") getting current read position!"; - errorText_ = errorStream_.str(); - MUTEX_UNLOCK( &stream_.mutex ); - error( RtAudioError::SYSTEM_ERROR ); - return; - } - if ( safeWritePointer != startSafeWritePointer && safeReadPointer != startSafeReadPointer ) break; - Sleep( 1 ); - } - - //assert( handle->dsBufferSize[0] == handle->dsBufferSize[1] ); - - handle->bufferPointer[0] = safeWritePointer + handle->dsPointerLeadTime[0]; - if ( handle->bufferPointer[0] >= handle->dsBufferSize[0] ) handle->bufferPointer[0] -= handle->dsBufferSize[0]; - handle->bufferPointer[1] = safeReadPointer; - } - else if ( stream_.mode == OUTPUT ) { - - // Set the proper nextWritePosition after initial startup. - LPDIRECTSOUNDBUFFER dsWriteBuffer = (LPDIRECTSOUNDBUFFER) handle->buffer[0]; - result = dsWriteBuffer->GetCurrentPosition( ¤tWritePointer, &safeWritePointer ); - if ( FAILED( result ) ) { - errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") getting current write position!"; - errorText_ = errorStream_.str(); - MUTEX_UNLOCK( &stream_.mutex ); - error( RtAudioError::SYSTEM_ERROR ); - return; - } - handle->bufferPointer[0] = safeWritePointer + handle->dsPointerLeadTime[0]; - if ( handle->bufferPointer[0] >= handle->dsBufferSize[0] ) handle->bufferPointer[0] -= handle->dsBufferSize[0]; - } - - buffersRolling = true; - } - - if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) { - - LPDIRECTSOUNDBUFFER dsBuffer = (LPDIRECTSOUNDBUFFER) handle->buffer[0]; - - if ( handle->drainCounter > 1 ) { // write zeros to the output stream - bufferBytes = stream_.bufferSize * stream_.nUserChannels[0]; - bufferBytes *= formatBytes( stream_.userFormat ); - memset( stream_.userBuffer[0], 0, bufferBytes ); - } - - // Setup parameters and do buffer conversion if necessary. - if ( stream_.doConvertBuffer[0] ) { - buffer = stream_.deviceBuffer; - convertBuffer( buffer, stream_.userBuffer[0], stream_.convertInfo[0] ); - bufferBytes = stream_.bufferSize * stream_.nDeviceChannels[0]; - bufferBytes *= formatBytes( stream_.deviceFormat[0] ); - } - else { - buffer = stream_.userBuffer[0]; - bufferBytes = stream_.bufferSize * stream_.nUserChannels[0]; - bufferBytes *= formatBytes( stream_.userFormat ); - } - - // No byte swapping necessary in DirectSound implementation. - - // Ahhh ... windoze. 16-bit data is signed but 8-bit data is - // unsigned. So, we need to convert our signed 8-bit data here to - // unsigned. - if ( stream_.deviceFormat[0] == RTAUDIO_SINT8 ) - for ( int i=0; i<bufferBytes; i++ ) buffer[i] = (unsigned char) ( buffer[i] + 128 ); - - DWORD dsBufferSize = handle->dsBufferSize[0]; - nextWritePointer = handle->bufferPointer[0]; - - DWORD endWrite, leadPointer; - while ( true ) { - // Find out where the read and "safe write" pointers are. - result = dsBuffer->GetCurrentPosition( ¤tWritePointer, &safeWritePointer ); - if ( FAILED( result ) ) { - errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") getting current write position!"; - errorText_ = errorStream_.str(); - MUTEX_UNLOCK( &stream_.mutex ); - error( RtAudioError::SYSTEM_ERROR ); - return; - } - - // We will copy our output buffer into the region between - // safeWritePointer and leadPointer. If leadPointer is not - // beyond the next endWrite position, wait until it is. - leadPointer = safeWritePointer + handle->dsPointerLeadTime[0]; - //std::cout << "safeWritePointer = " << safeWritePointer << ", leadPointer = " << leadPointer << ", nextWritePointer = " << nextWritePointer << std::endl; - if ( leadPointer > dsBufferSize ) leadPointer -= dsBufferSize; - if ( leadPointer < nextWritePointer ) leadPointer += dsBufferSize; // unwrap offset - endWrite = nextWritePointer + bufferBytes; - - // Check whether the entire write region is behind the play pointer. - if ( leadPointer >= endWrite ) break; - - // If we are here, then we must wait until the leadPointer advances - // beyond the end of our next write region. We use the - // Sleep() function to suspend operation until that happens. - double millis = ( endWrite - leadPointer ) * 1000.0; - millis /= ( formatBytes( stream_.deviceFormat[0]) * stream_.nDeviceChannels[0] * stream_.sampleRate); - if ( millis < 1.0 ) millis = 1.0; - Sleep( (DWORD) millis ); - } - - if ( dsPointerBetween( nextWritePointer, safeWritePointer, currentWritePointer, dsBufferSize ) - || dsPointerBetween( endWrite, safeWritePointer, currentWritePointer, dsBufferSize ) ) { - // We've strayed into the forbidden zone ... resync the read pointer. - handle->xrun[0] = true; - nextWritePointer = safeWritePointer + handle->dsPointerLeadTime[0] - bufferBytes; - if ( nextWritePointer >= dsBufferSize ) nextWritePointer -= dsBufferSize; - handle->bufferPointer[0] = nextWritePointer; - endWrite = nextWritePointer + bufferBytes; - } - - // Lock free space in the buffer - result = dsBuffer->Lock( nextWritePointer, bufferBytes, &buffer1, - &bufferSize1, &buffer2, &bufferSize2, 0 ); - if ( FAILED( result ) ) { - errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") locking buffer during playback!"; - errorText_ = errorStream_.str(); - MUTEX_UNLOCK( &stream_.mutex ); - error( RtAudioError::SYSTEM_ERROR ); - return; - } - - // Copy our buffer into the DS buffer - CopyMemory( buffer1, buffer, bufferSize1 ); - if ( buffer2 != NULL ) CopyMemory( buffer2, buffer+bufferSize1, bufferSize2 ); - - // Update our buffer offset and unlock sound buffer - dsBuffer->Unlock( buffer1, bufferSize1, buffer2, bufferSize2 ); - if ( FAILED( result ) ) { - errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") unlocking buffer during playback!"; - errorText_ = errorStream_.str(); - MUTEX_UNLOCK( &stream_.mutex ); - error( RtAudioError::SYSTEM_ERROR ); - return; - } - nextWritePointer = ( nextWritePointer + bufferSize1 + bufferSize2 ) % dsBufferSize; - handle->bufferPointer[0] = nextWritePointer; - } - - // Don't bother draining input - if ( handle->drainCounter ) { - handle->drainCounter++; - goto unlock; - } - - if ( stream_.mode == INPUT || stream_.mode == DUPLEX ) { - - // Setup parameters. - if ( stream_.doConvertBuffer[1] ) { - buffer = stream_.deviceBuffer; - bufferBytes = stream_.bufferSize * stream_.nDeviceChannels[1]; - bufferBytes *= formatBytes( stream_.deviceFormat[1] ); - } - else { - buffer = stream_.userBuffer[1]; - bufferBytes = stream_.bufferSize * stream_.nUserChannels[1]; - bufferBytes *= formatBytes( stream_.userFormat ); - } - - LPDIRECTSOUNDCAPTUREBUFFER dsBuffer = (LPDIRECTSOUNDCAPTUREBUFFER) handle->buffer[1]; - long nextReadPointer = handle->bufferPointer[1]; - DWORD dsBufferSize = handle->dsBufferSize[1]; - - // Find out where the write and "safe read" pointers are. - result = dsBuffer->GetCurrentPosition( ¤tReadPointer, &safeReadPointer ); - if ( FAILED( result ) ) { - errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") getting current read position!"; - errorText_ = errorStream_.str(); - MUTEX_UNLOCK( &stream_.mutex ); - error( RtAudioError::SYSTEM_ERROR ); - return; - } - - if ( safeReadPointer < (DWORD)nextReadPointer ) safeReadPointer += dsBufferSize; // unwrap offset - DWORD endRead = nextReadPointer + bufferBytes; - - // Handling depends on whether we are INPUT or DUPLEX. - // If we're in INPUT mode then waiting is a good thing. If we're in DUPLEX mode, - // then a wait here will drag the write pointers into the forbidden zone. - // - // In DUPLEX mode, rather than wait, we will back off the read pointer until - // it's in a safe position. This causes dropouts, but it seems to be the only - // practical way to sync up the read and write pointers reliably, given the - // the very complex relationship between phase and increment of the read and write - // pointers. - // - // In order to minimize audible dropouts in DUPLEX mode, we will - // provide a pre-roll period of 0.5 seconds in which we return - // zeros from the read buffer while the pointers sync up. - - if ( stream_.mode == DUPLEX ) { - if ( safeReadPointer < endRead ) { - if ( duplexPrerollBytes <= 0 ) { - // Pre-roll time over. Be more agressive. - int adjustment = endRead-safeReadPointer; - - handle->xrun[1] = true; - // Two cases: - // - large adjustments: we've probably run out of CPU cycles, so just resync exactly, - // and perform fine adjustments later. - // - small adjustments: back off by twice as much. - if ( adjustment >= 2*bufferBytes ) - nextReadPointer = safeReadPointer-2*bufferBytes; - else - nextReadPointer = safeReadPointer-bufferBytes-adjustment; - - if ( nextReadPointer < 0 ) nextReadPointer += dsBufferSize; - - } - else { - // In pre=roll time. Just do it. - nextReadPointer = safeReadPointer - bufferBytes; - while ( nextReadPointer < 0 ) nextReadPointer += dsBufferSize; - } - endRead = nextReadPointer + bufferBytes; - } - } - else { // mode == INPUT - while ( safeReadPointer < endRead && stream_.callbackInfo.isRunning ) { - // See comments for playback. - double millis = (endRead - safeReadPointer) * 1000.0; - millis /= ( formatBytes(stream_.deviceFormat[1]) * stream_.nDeviceChannels[1] * stream_.sampleRate); - if ( millis < 1.0 ) millis = 1.0; - Sleep( (DWORD) millis ); - - // Wake up and find out where we are now. - result = dsBuffer->GetCurrentPosition( ¤tReadPointer, &safeReadPointer ); - if ( FAILED( result ) ) { - errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") getting current read position!"; - errorText_ = errorStream_.str(); - MUTEX_UNLOCK( &stream_.mutex ); - error( RtAudioError::SYSTEM_ERROR ); - return; - } - - if ( safeReadPointer < (DWORD)nextReadPointer ) safeReadPointer += dsBufferSize; // unwrap offset - } - } - - // Lock free space in the buffer - result = dsBuffer->Lock( nextReadPointer, bufferBytes, &buffer1, - &bufferSize1, &buffer2, &bufferSize2, 0 ); - if ( FAILED( result ) ) { - errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") locking capture buffer!"; - errorText_ = errorStream_.str(); - MUTEX_UNLOCK( &stream_.mutex ); - error( RtAudioError::SYSTEM_ERROR ); - return; - } - - if ( duplexPrerollBytes <= 0 ) { - // Copy our buffer into the DS buffer - CopyMemory( buffer, buffer1, bufferSize1 ); - if ( buffer2 != NULL ) CopyMemory( buffer+bufferSize1, buffer2, bufferSize2 ); - } - else { - memset( buffer, 0, bufferSize1 ); - if ( buffer2 != NULL ) memset( buffer + bufferSize1, 0, bufferSize2 ); - duplexPrerollBytes -= bufferSize1 + bufferSize2; - } - - // Update our buffer offset and unlock sound buffer - nextReadPointer = ( nextReadPointer + bufferSize1 + bufferSize2 ) % dsBufferSize; - dsBuffer->Unlock( buffer1, bufferSize1, buffer2, bufferSize2 ); - if ( FAILED( result ) ) { - errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") unlocking capture buffer!"; - errorText_ = errorStream_.str(); - MUTEX_UNLOCK( &stream_.mutex ); - error( RtAudioError::SYSTEM_ERROR ); - return; - } - handle->bufferPointer[1] = nextReadPointer; - - // No byte swapping necessary in DirectSound implementation. - - // If necessary, convert 8-bit data from unsigned to signed. - if ( stream_.deviceFormat[1] == RTAUDIO_SINT8 ) - for ( int j=0; j<bufferBytes; j++ ) buffer[j] = (signed char) ( buffer[j] - 128 ); - - // Do buffer conversion if necessary. - if ( stream_.doConvertBuffer[1] ) - convertBuffer( stream_.userBuffer[1], stream_.deviceBuffer, stream_.convertInfo[1] ); - } - - unlock: - MUTEX_UNLOCK( &stream_.mutex ); - RtApi::tickStreamTime(); -} - -// Definitions for utility functions and callbacks -// specific to the DirectSound implementation. - -static unsigned __stdcall callbackHandler( void *ptr ) -{ - CallbackInfo *info = (CallbackInfo *) ptr; - RtApiDs *object = (RtApiDs *) info->object; - bool* isRunning = &info->isRunning; - - while ( *isRunning == true ) { - object->callbackEvent(); - } - - _endthreadex( 0 ); - return 0; -} - -static BOOL CALLBACK deviceQueryCallback( LPGUID lpguid, - LPCTSTR description, - LPCTSTR /*module*/, - LPVOID lpContext ) -{ - struct DsProbeData& probeInfo = *(struct DsProbeData*) lpContext; - std::vector<struct DsDevice>& dsDevices = *probeInfo.dsDevices; - - HRESULT hr; - bool validDevice = false; - if ( probeInfo.isInput == true ) { - DSCCAPS caps; - LPDIRECTSOUNDCAPTURE object; - - hr = DirectSoundCaptureCreate( lpguid, &object, NULL ); - if ( hr != DS_OK ) return TRUE; - - caps.dwSize = sizeof(caps); - hr = object->GetCaps( &caps ); - if ( hr == DS_OK ) { - if ( caps.dwChannels > 0 && caps.dwFormats > 0 ) - validDevice = true; - } - object->Release(); - } - else { - DSCAPS caps; - LPDIRECTSOUND object; - hr = DirectSoundCreate( lpguid, &object, NULL ); - if ( hr != DS_OK ) return TRUE; - - caps.dwSize = sizeof(caps); - hr = object->GetCaps( &caps ); - if ( hr == DS_OK ) { - if ( caps.dwFlags & DSCAPS_PRIMARYMONO || caps.dwFlags & DSCAPS_PRIMARYSTEREO ) - validDevice = true; - } - object->Release(); - } - - // If good device, then save its name and guid. - std::string name = convertCharPointerToStdString( description ); - //if ( name == "Primary Sound Driver" || name == "Primary Sound Capture Driver" ) - if ( lpguid == NULL ) - name = "Default Device"; - if ( validDevice ) { - for ( unsigned int i=0; i<dsDevices.size(); i++ ) { - if ( dsDevices[i].name == name ) { - dsDevices[i].found = true; - if ( probeInfo.isInput ) { - dsDevices[i].id[1] = lpguid; - dsDevices[i].validId[1] = true; - } - else { - dsDevices[i].id[0] = lpguid; - dsDevices[i].validId[0] = true; - } - return TRUE; - } - } - - DsDevice device; - device.name = name; - device.found = true; - if ( probeInfo.isInput ) { - device.id[1] = lpguid; - device.validId[1] = true; - } - else { - device.id[0] = lpguid; - device.validId[0] = true; - } - dsDevices.push_back( device ); - } - - return TRUE; -} - -static const char* getErrorString( int code ) -{ - switch ( code ) { - - case DSERR_ALLOCATED: - return "Already allocated"; - - case DSERR_CONTROLUNAVAIL: - return "Control unavailable"; - - case DSERR_INVALIDPARAM: - return "Invalid parameter"; - - case DSERR_INVALIDCALL: - return "Invalid call"; - - case DSERR_GENERIC: - return "Generic error"; - - case DSERR_PRIOLEVELNEEDED: - return "Priority level needed"; - - case DSERR_OUTOFMEMORY: - return "Out of memory"; - - case DSERR_BADFORMAT: - return "The sample rate or the channel format is not supported"; - - case DSERR_UNSUPPORTED: - return "Not supported"; - - case DSERR_NODRIVER: - return "No driver"; - - case DSERR_ALREADYINITIALIZED: - return "Already initialized"; - - case DSERR_NOAGGREGATION: - return "No aggregation"; - - case DSERR_BUFFERLOST: - return "Buffer lost"; - - case DSERR_OTHERAPPHASPRIO: - return "Another application already has priority"; - - case DSERR_UNINITIALIZED: - return "Uninitialized"; - - default: - return "DirectSound unknown error"; - } -} -//******************** End of __WINDOWS_DS__ *********************// -#endif - - -#if defined(__LINUX_ALSA__) - -#include <alsa/asoundlib.h> -#include <unistd.h> - - // A structure to hold various information related to the ALSA API - // implementation. -struct AlsaHandle { - snd_pcm_t *handles[2]; - bool synchronized; - bool xrun[2]; - pthread_cond_t runnable_cv; - bool runnable; - - AlsaHandle() - :synchronized(false), runnable(false) { xrun[0] = false; xrun[1] = false; } -}; - -static void *alsaCallbackHandler( void * ptr ); - -RtApiAlsa :: RtApiAlsa() -{ - // Nothing to do here. -} - -RtApiAlsa :: ~RtApiAlsa() -{ - if ( stream_.state != STREAM_CLOSED ) closeStream(); -} - -unsigned int RtApiAlsa :: getDeviceCount( void ) -{ - unsigned nDevices = 0; - int result, subdevice, card; - char name[64]; - snd_ctl_t *handle; - - // Count cards and devices - card = -1; - snd_card_next( &card ); - while ( card >= 0 ) { - sprintf( name, "hw:%d", card ); - result = snd_ctl_open( &handle, name, 0 ); - if ( result < 0 ) { - errorStream_ << "RtApiAlsa::getDeviceCount: control open, card = " << card << ", " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - goto nextcard; - } - subdevice = -1; - while( 1 ) { - result = snd_ctl_pcm_next_device( handle, &subdevice ); - if ( result < 0 ) { - errorStream_ << "RtApiAlsa::getDeviceCount: control next device, card = " << card << ", " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - break; - } - if ( subdevice < 0 ) - break; - nDevices++; - } - nextcard: - snd_ctl_close( handle ); - snd_card_next( &card ); - } - - result = snd_ctl_open( &handle, "default", 0 ); - if (result == 0) { - nDevices++; - snd_ctl_close( handle ); - } - - return nDevices; -} - -RtAudio::DeviceInfo RtApiAlsa :: getDeviceInfo( unsigned int device ) -{ - RtAudio::DeviceInfo info; - info.probed = false; - - unsigned nDevices = 0; - int result, subdevice, card; - char name[64]; - snd_ctl_t *chandle; - - // Count cards and devices - card = -1; - subdevice = -1; - snd_card_next( &card ); - while ( card >= 0 ) { - sprintf( name, "hw:%d", card ); - result = snd_ctl_open( &chandle, name, SND_CTL_NONBLOCK ); - if ( result < 0 ) { - errorStream_ << "RtApiAlsa::getDeviceInfo: control open, card = " << card << ", " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - goto nextcard; - } - subdevice = -1; - while( 1 ) { - result = snd_ctl_pcm_next_device( chandle, &subdevice ); - if ( result < 0 ) { - errorStream_ << "RtApiAlsa::getDeviceInfo: control next device, card = " << card << ", " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - break; - } - if ( subdevice < 0 ) break; - if ( nDevices == device ) { - sprintf( name, "hw:%d,%d", card, subdevice ); - goto foundDevice; - } - nDevices++; - } - nextcard: - snd_ctl_close( chandle ); - snd_card_next( &card ); - } - - result = snd_ctl_open( &chandle, "default", SND_CTL_NONBLOCK ); - if ( result == 0 ) { - if ( nDevices == device ) { - strcpy( name, "default" ); - goto foundDevice; - } - nDevices++; - } - - if ( nDevices == 0 ) { - errorText_ = "RtApiAlsa::getDeviceInfo: no devices found!"; - error( RtAudioError::INVALID_USE ); - return info; - } - - if ( device >= nDevices ) { - errorText_ = "RtApiAlsa::getDeviceInfo: device ID is invalid!"; - error( RtAudioError::INVALID_USE ); - return info; - } - - foundDevice: - - // If a stream is already open, we cannot probe the stream devices. - // Thus, use the saved results. - if ( stream_.state != STREAM_CLOSED && - ( stream_.device[0] == device || stream_.device[1] == device ) ) { - snd_ctl_close( chandle ); - if ( device >= devices_.size() ) { - errorText_ = "RtApiAlsa::getDeviceInfo: device ID was not present before stream was opened."; - error( RtAudioError::WARNING ); - return info; - } - return devices_[ device ]; - } - - int openMode = SND_PCM_ASYNC; - snd_pcm_stream_t stream; - snd_pcm_info_t *pcminfo; - snd_pcm_info_alloca( &pcminfo ); - snd_pcm_t *phandle; - snd_pcm_hw_params_t *params; - snd_pcm_hw_params_alloca( ¶ms ); - - // First try for playback unless default device (which has subdev -1) - stream = SND_PCM_STREAM_PLAYBACK; - snd_pcm_info_set_stream( pcminfo, stream ); - if ( subdevice != -1 ) { - snd_pcm_info_set_device( pcminfo, subdevice ); - snd_pcm_info_set_subdevice( pcminfo, 0 ); - - result = snd_ctl_pcm_info( chandle, pcminfo ); - if ( result < 0 ) { - // Device probably doesn't support playback. - goto captureProbe; - } - } - - result = snd_pcm_open( &phandle, name, stream, openMode | SND_PCM_NONBLOCK ); - if ( result < 0 ) { - errorStream_ << "RtApiAlsa::getDeviceInfo: snd_pcm_open error for device (" << name << "), " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - goto captureProbe; - } - - // The device is open ... fill the parameter structure. - result = snd_pcm_hw_params_any( phandle, params ); - if ( result < 0 ) { - snd_pcm_close( phandle ); - errorStream_ << "RtApiAlsa::getDeviceInfo: snd_pcm_hw_params error for device (" << name << "), " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - goto captureProbe; - } - - // Get output channel information. - unsigned int value; - result = snd_pcm_hw_params_get_channels_max( params, &value ); - if ( result < 0 ) { - snd_pcm_close( phandle ); - errorStream_ << "RtApiAlsa::getDeviceInfo: error getting device (" << name << ") output channels, " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - goto captureProbe; - } - info.outputChannels = value; - snd_pcm_close( phandle ); - - captureProbe: - stream = SND_PCM_STREAM_CAPTURE; - snd_pcm_info_set_stream( pcminfo, stream ); - - // Now try for capture unless default device (with subdev = -1) - if ( subdevice != -1 ) { - result = snd_ctl_pcm_info( chandle, pcminfo ); - snd_ctl_close( chandle ); - if ( result < 0 ) { - // Device probably doesn't support capture. - if ( info.outputChannels == 0 ) return info; - goto probeParameters; - } - } - else - snd_ctl_close( chandle ); - - result = snd_pcm_open( &phandle, name, stream, openMode | SND_PCM_NONBLOCK); - if ( result < 0 ) { - errorStream_ << "RtApiAlsa::getDeviceInfo: snd_pcm_open error for device (" << name << "), " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - if ( info.outputChannels == 0 ) return info; - goto probeParameters; - } - - // The device is open ... fill the parameter structure. - result = snd_pcm_hw_params_any( phandle, params ); - if ( result < 0 ) { - snd_pcm_close( phandle ); - errorStream_ << "RtApiAlsa::getDeviceInfo: snd_pcm_hw_params error for device (" << name << "), " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - if ( info.outputChannels == 0 ) return info; - goto probeParameters; - } - - result = snd_pcm_hw_params_get_channels_max( params, &value ); - if ( result < 0 ) { - snd_pcm_close( phandle ); - errorStream_ << "RtApiAlsa::getDeviceInfo: error getting device (" << name << ") input channels, " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - if ( info.outputChannels == 0 ) return info; - goto probeParameters; - } - info.inputChannels = value; - snd_pcm_close( phandle ); - - // If device opens for both playback and capture, we determine the channels. - if ( info.outputChannels > 0 && info.inputChannels > 0 ) - info.duplexChannels = (info.outputChannels > info.inputChannels) ? info.inputChannels : info.outputChannels; - - // ALSA doesn't provide default devices so we'll use the first available one. - if ( device == 0 && info.outputChannels > 0 ) - info.isDefaultOutput = true; - if ( device == 0 && info.inputChannels > 0 ) - info.isDefaultInput = true; - - probeParameters: - // At this point, we just need to figure out the supported data - // formats and sample rates. We'll proceed by opening the device in - // the direction with the maximum number of channels, or playback if - // they are equal. This might limit our sample rate options, but so - // be it. - - if ( info.outputChannels >= info.inputChannels ) - stream = SND_PCM_STREAM_PLAYBACK; - else - stream = SND_PCM_STREAM_CAPTURE; - snd_pcm_info_set_stream( pcminfo, stream ); - - result = snd_pcm_open( &phandle, name, stream, openMode | SND_PCM_NONBLOCK); - if ( result < 0 ) { - errorStream_ << "RtApiAlsa::getDeviceInfo: snd_pcm_open error for device (" << name << "), " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - return info; - } - - // The device is open ... fill the parameter structure. - result = snd_pcm_hw_params_any( phandle, params ); - if ( result < 0 ) { - snd_pcm_close( phandle ); - errorStream_ << "RtApiAlsa::getDeviceInfo: snd_pcm_hw_params error for device (" << name << "), " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - return info; - } - - // Test our discrete set of sample rate values. - info.sampleRates.clear(); - for ( unsigned int i=0; i<MAX_SAMPLE_RATES; i++ ) { - if ( snd_pcm_hw_params_test_rate( phandle, params, SAMPLE_RATES[i], 0 ) == 0 ) { - info.sampleRates.push_back( SAMPLE_RATES[i] ); - - if ( !info.preferredSampleRate || ( SAMPLE_RATES[i] <= 48000 && SAMPLE_RATES[i] > info.preferredSampleRate ) ) - info.preferredSampleRate = SAMPLE_RATES[i]; - } - } - if ( info.sampleRates.size() == 0 ) { - snd_pcm_close( phandle ); - errorStream_ << "RtApiAlsa::getDeviceInfo: no supported sample rates found for device (" << name << ")."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - return info; - } - - // Probe the supported data formats ... we don't care about endian-ness just yet - snd_pcm_format_t format; - info.nativeFormats = 0; - format = SND_PCM_FORMAT_S8; - if ( snd_pcm_hw_params_test_format( phandle, params, format ) == 0 ) - info.nativeFormats |= RTAUDIO_SINT8; - format = SND_PCM_FORMAT_S16; - if ( snd_pcm_hw_params_test_format( phandle, params, format ) == 0 ) - info.nativeFormats |= RTAUDIO_SINT16; - format = SND_PCM_FORMAT_S24; - if ( snd_pcm_hw_params_test_format( phandle, params, format ) == 0 ) - info.nativeFormats |= RTAUDIO_SINT24; - format = SND_PCM_FORMAT_S32; - if ( snd_pcm_hw_params_test_format( phandle, params, format ) == 0 ) - info.nativeFormats |= RTAUDIO_SINT32; - format = SND_PCM_FORMAT_FLOAT; - if ( snd_pcm_hw_params_test_format( phandle, params, format ) == 0 ) - info.nativeFormats |= RTAUDIO_FLOAT32; - format = SND_PCM_FORMAT_FLOAT64; - if ( snd_pcm_hw_params_test_format( phandle, params, format ) == 0 ) - info.nativeFormats |= RTAUDIO_FLOAT64; - - // Check that we have at least one supported format - if ( info.nativeFormats == 0 ) { - snd_pcm_close( phandle ); - errorStream_ << "RtApiAlsa::getDeviceInfo: pcm device (" << name << ") data format not supported by RtAudio."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - return info; - } - - // Get the device name - char *cardname; - result = snd_card_get_name( card, &cardname ); - if ( result >= 0 ) { - sprintf( name, "hw:%s,%d", cardname, subdevice ); - free( cardname ); - } - info.name = name; - - // That's all ... close the device and return - snd_pcm_close( phandle ); - info.probed = true; - return info; -} - -void RtApiAlsa :: saveDeviceInfo( void ) -{ - devices_.clear(); - - unsigned int nDevices = getDeviceCount(); - devices_.resize( nDevices ); - for ( unsigned int i=0; i<nDevices; i++ ) - devices_[i] = getDeviceInfo( i ); -} - -bool RtApiAlsa :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, - unsigned int firstChannel, unsigned int sampleRate, - RtAudioFormat format, unsigned int *bufferSize, - RtAudio::StreamOptions *options ) - -{ -#if defined(__RTAUDIO_DEBUG__) - snd_output_t *out; - snd_output_stdio_attach(&out, stderr, 0); -#endif - - // I'm not using the "plug" interface ... too much inconsistent behavior. - - unsigned nDevices = 0; - int result, subdevice, card; - char name[64]; - snd_ctl_t *chandle; - - if ( options && options->flags & RTAUDIO_ALSA_USE_DEFAULT ) - snprintf(name, sizeof(name), "%s", "default"); - else { - // Count cards and devices - card = -1; - snd_card_next( &card ); - while ( card >= 0 ) { - sprintf( name, "hw:%d", card ); - result = snd_ctl_open( &chandle, name, SND_CTL_NONBLOCK ); - if ( result < 0 ) { - errorStream_ << "RtApiAlsa::probeDeviceOpen: control open, card = " << card << ", " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - return FAILURE; - } - subdevice = -1; - while( 1 ) { - result = snd_ctl_pcm_next_device( chandle, &subdevice ); - if ( result < 0 ) break; - if ( subdevice < 0 ) break; - if ( nDevices == device ) { - sprintf( name, "hw:%d,%d", card, subdevice ); - snd_ctl_close( chandle ); - goto foundDevice; - } - nDevices++; - } - snd_ctl_close( chandle ); - snd_card_next( &card ); - } - - result = snd_ctl_open( &chandle, "default", SND_CTL_NONBLOCK ); - if ( result == 0 ) { - if ( nDevices == device ) { - strcpy( name, "default" ); - goto foundDevice; - } - nDevices++; - } - - if ( nDevices == 0 ) { - // This should not happen because a check is made before this function is called. - errorText_ = "RtApiAlsa::probeDeviceOpen: no devices found!"; - return FAILURE; - } - - if ( device >= nDevices ) { - // This should not happen because a check is made before this function is called. - errorText_ = "RtApiAlsa::probeDeviceOpen: device ID is invalid!"; - return FAILURE; - } - } - - foundDevice: - - // The getDeviceInfo() function will not work for a device that is - // already open. Thus, we'll probe the system before opening a - // stream and save the results for use by getDeviceInfo(). - if ( mode == OUTPUT || ( mode == INPUT && stream_.mode != OUTPUT ) ) // only do once - this->saveDeviceInfo(); - - snd_pcm_stream_t stream; - if ( mode == OUTPUT ) - stream = SND_PCM_STREAM_PLAYBACK; - else - stream = SND_PCM_STREAM_CAPTURE; - - snd_pcm_t *phandle; - int openMode = SND_PCM_ASYNC; - result = snd_pcm_open( &phandle, name, stream, openMode ); - if ( result < 0 ) { - if ( mode == OUTPUT ) - errorStream_ << "RtApiAlsa::probeDeviceOpen: pcm device (" << name << ") won't open for output."; - else - errorStream_ << "RtApiAlsa::probeDeviceOpen: pcm device (" << name << ") won't open for input."; - errorText_ = errorStream_.str(); - return FAILURE; - } - - // Fill the parameter structure. - snd_pcm_hw_params_t *hw_params; - snd_pcm_hw_params_alloca( &hw_params ); - result = snd_pcm_hw_params_any( phandle, hw_params ); - if ( result < 0 ) { - snd_pcm_close( phandle ); - errorStream_ << "RtApiAlsa::probeDeviceOpen: error getting pcm device (" << name << ") parameters, " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - return FAILURE; - } - -#if defined(__RTAUDIO_DEBUG__) - fprintf( stderr, "\nRtApiAlsa: dump hardware params just after device open:\n\n" ); - snd_pcm_hw_params_dump( hw_params, out ); -#endif - - // Set access ... check user preference. - if ( options && options->flags & RTAUDIO_NONINTERLEAVED ) { - stream_.userInterleaved = false; - result = snd_pcm_hw_params_set_access( phandle, hw_params, SND_PCM_ACCESS_RW_NONINTERLEAVED ); - if ( result < 0 ) { - result = snd_pcm_hw_params_set_access( phandle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED ); - stream_.deviceInterleaved[mode] = true; - } - else - stream_.deviceInterleaved[mode] = false; - } - else { - stream_.userInterleaved = true; - result = snd_pcm_hw_params_set_access( phandle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED ); - if ( result < 0 ) { - result = snd_pcm_hw_params_set_access( phandle, hw_params, SND_PCM_ACCESS_RW_NONINTERLEAVED ); - stream_.deviceInterleaved[mode] = false; - } - else - stream_.deviceInterleaved[mode] = true; - } - - if ( result < 0 ) { - snd_pcm_close( phandle ); - errorStream_ << "RtApiAlsa::probeDeviceOpen: error setting pcm device (" << name << ") access, " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - return FAILURE; - } - - // Determine how to set the device format. - stream_.userFormat = format; - snd_pcm_format_t deviceFormat = SND_PCM_FORMAT_UNKNOWN; - - if ( format == RTAUDIO_SINT8 ) - deviceFormat = SND_PCM_FORMAT_S8; - else if ( format == RTAUDIO_SINT16 ) - deviceFormat = SND_PCM_FORMAT_S16; - else if ( format == RTAUDIO_SINT24 ) - deviceFormat = SND_PCM_FORMAT_S24; - else if ( format == RTAUDIO_SINT32 ) - deviceFormat = SND_PCM_FORMAT_S32; - else if ( format == RTAUDIO_FLOAT32 ) - deviceFormat = SND_PCM_FORMAT_FLOAT; - else if ( format == RTAUDIO_FLOAT64 ) - deviceFormat = SND_PCM_FORMAT_FLOAT64; - - if ( snd_pcm_hw_params_test_format(phandle, hw_params, deviceFormat) == 0) { - stream_.deviceFormat[mode] = format; - goto setFormat; - } - - // The user requested format is not natively supported by the device. - deviceFormat = SND_PCM_FORMAT_FLOAT64; - if ( snd_pcm_hw_params_test_format( phandle, hw_params, deviceFormat ) == 0 ) { - stream_.deviceFormat[mode] = RTAUDIO_FLOAT64; - goto setFormat; - } - - deviceFormat = SND_PCM_FORMAT_FLOAT; - if ( snd_pcm_hw_params_test_format(phandle, hw_params, deviceFormat ) == 0 ) { - stream_.deviceFormat[mode] = RTAUDIO_FLOAT32; - goto setFormat; - } - - deviceFormat = SND_PCM_FORMAT_S32; - if ( snd_pcm_hw_params_test_format(phandle, hw_params, deviceFormat ) == 0 ) { - stream_.deviceFormat[mode] = RTAUDIO_SINT32; - goto setFormat; - } - - deviceFormat = SND_PCM_FORMAT_S24; - if ( snd_pcm_hw_params_test_format(phandle, hw_params, deviceFormat ) == 0 ) { - stream_.deviceFormat[mode] = RTAUDIO_SINT24; - goto setFormat; - } - - deviceFormat = SND_PCM_FORMAT_S16; - if ( snd_pcm_hw_params_test_format(phandle, hw_params, deviceFormat ) == 0 ) { - stream_.deviceFormat[mode] = RTAUDIO_SINT16; - goto setFormat; - } - - deviceFormat = SND_PCM_FORMAT_S8; - if ( snd_pcm_hw_params_test_format(phandle, hw_params, deviceFormat ) == 0 ) { - stream_.deviceFormat[mode] = RTAUDIO_SINT8; - goto setFormat; - } - - // If we get here, no supported format was found. - snd_pcm_close( phandle ); - errorStream_ << "RtApiAlsa::probeDeviceOpen: pcm device " << device << " data format not supported by RtAudio."; - errorText_ = errorStream_.str(); - return FAILURE; - - setFormat: - result = snd_pcm_hw_params_set_format( phandle, hw_params, deviceFormat ); - if ( result < 0 ) { - snd_pcm_close( phandle ); - errorStream_ << "RtApiAlsa::probeDeviceOpen: error setting pcm device (" << name << ") data format, " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - return FAILURE; - } - - // Determine whether byte-swaping is necessary. - stream_.doByteSwap[mode] = false; - if ( deviceFormat != SND_PCM_FORMAT_S8 ) { - result = snd_pcm_format_cpu_endian( deviceFormat ); - if ( result == 0 ) - stream_.doByteSwap[mode] = true; - else if (result < 0) { - snd_pcm_close( phandle ); - errorStream_ << "RtApiAlsa::probeDeviceOpen: error getting pcm device (" << name << ") endian-ness, " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - return FAILURE; - } - } - - // Set the sample rate. - result = snd_pcm_hw_params_set_rate_near( phandle, hw_params, (unsigned int*) &sampleRate, 0 ); - if ( result < 0 ) { - snd_pcm_close( phandle ); - errorStream_ << "RtApiAlsa::probeDeviceOpen: error setting sample rate on device (" << name << "), " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - return FAILURE; - } - - // Determine the number of channels for this device. We support a possible - // minimum device channel number > than the value requested by the user. - stream_.nUserChannels[mode] = channels; - unsigned int value; - result = snd_pcm_hw_params_get_channels_max( hw_params, &value ); - unsigned int deviceChannels = value; - if ( result < 0 || deviceChannels < channels + firstChannel ) { - snd_pcm_close( phandle ); - errorStream_ << "RtApiAlsa::probeDeviceOpen: requested channel parameters not supported by device (" << name << "), " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - return FAILURE; - } - - result = snd_pcm_hw_params_get_channels_min( hw_params, &value ); - if ( result < 0 ) { - snd_pcm_close( phandle ); - errorStream_ << "RtApiAlsa::probeDeviceOpen: error getting minimum channels for device (" << name << "), " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - return FAILURE; - } - deviceChannels = value; - if ( deviceChannels < channels + firstChannel ) deviceChannels = channels + firstChannel; - stream_.nDeviceChannels[mode] = deviceChannels; - - // Set the device channels. - result = snd_pcm_hw_params_set_channels( phandle, hw_params, deviceChannels ); - if ( result < 0 ) { - snd_pcm_close( phandle ); - errorStream_ << "RtApiAlsa::probeDeviceOpen: error setting channels for device (" << name << "), " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - return FAILURE; - } - - // Set the buffer (or period) size. - int dir = 0; - snd_pcm_uframes_t periodSize = *bufferSize; - result = snd_pcm_hw_params_set_period_size_near( phandle, hw_params, &periodSize, &dir ); - if ( result < 0 ) { - snd_pcm_close( phandle ); - errorStream_ << "RtApiAlsa::probeDeviceOpen: error setting period size for device (" << name << "), " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - return FAILURE; - } - *bufferSize = periodSize; - - // Set the buffer number, which in ALSA is referred to as the "period". - unsigned int periods = 0; - if ( options && options->flags & RTAUDIO_MINIMIZE_LATENCY ) periods = 2; - if ( options && options->numberOfBuffers > 0 ) periods = options->numberOfBuffers; - if ( periods < 2 ) periods = 4; // a fairly safe default value - result = snd_pcm_hw_params_set_periods_near( phandle, hw_params, &periods, &dir ); - if ( result < 0 ) { - snd_pcm_close( phandle ); - errorStream_ << "RtApiAlsa::probeDeviceOpen: error setting periods for device (" << name << "), " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - return FAILURE; - } - - // If attempting to setup a duplex stream, the bufferSize parameter - // MUST be the same in both directions! - if ( stream_.mode == OUTPUT && mode == INPUT && *bufferSize != stream_.bufferSize ) { - snd_pcm_close( phandle ); - errorStream_ << "RtApiAlsa::probeDeviceOpen: system error setting buffer size for duplex stream on device (" << name << ")."; - errorText_ = errorStream_.str(); - return FAILURE; - } - - stream_.bufferSize = *bufferSize; - - // Install the hardware configuration - result = snd_pcm_hw_params( phandle, hw_params ); - if ( result < 0 ) { - snd_pcm_close( phandle ); - errorStream_ << "RtApiAlsa::probeDeviceOpen: error installing hardware configuration on device (" << name << "), " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - return FAILURE; - } - -#if defined(__RTAUDIO_DEBUG__) - fprintf(stderr, "\nRtApiAlsa: dump hardware params after installation:\n\n"); - snd_pcm_hw_params_dump( hw_params, out ); -#endif - - // Set the software configuration to fill buffers with zeros and prevent device stopping on xruns. - snd_pcm_sw_params_t *sw_params = NULL; - snd_pcm_sw_params_alloca( &sw_params ); - snd_pcm_sw_params_current( phandle, sw_params ); - snd_pcm_sw_params_set_start_threshold( phandle, sw_params, *bufferSize ); - snd_pcm_sw_params_set_stop_threshold( phandle, sw_params, ULONG_MAX ); - snd_pcm_sw_params_set_silence_threshold( phandle, sw_params, 0 ); - - // The following two settings were suggested by Theo Veenker - //snd_pcm_sw_params_set_avail_min( phandle, sw_params, *bufferSize ); - //snd_pcm_sw_params_set_xfer_align( phandle, sw_params, 1 ); - - // here are two options for a fix - //snd_pcm_sw_params_set_silence_size( phandle, sw_params, ULONG_MAX ); - snd_pcm_uframes_t val; - snd_pcm_sw_params_get_boundary( sw_params, &val ); - snd_pcm_sw_params_set_silence_size( phandle, sw_params, val ); - - result = snd_pcm_sw_params( phandle, sw_params ); - if ( result < 0 ) { - snd_pcm_close( phandle ); - errorStream_ << "RtApiAlsa::probeDeviceOpen: error installing software configuration on device (" << name << "), " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - return FAILURE; - } - -#if defined(__RTAUDIO_DEBUG__) - fprintf(stderr, "\nRtApiAlsa: dump software params after installation:\n\n"); - snd_pcm_sw_params_dump( sw_params, out ); -#endif - - // Set flags for buffer conversion - stream_.doConvertBuffer[mode] = false; - if ( stream_.userFormat != stream_.deviceFormat[mode] ) - stream_.doConvertBuffer[mode] = true; - if ( stream_.nUserChannels[mode] < stream_.nDeviceChannels[mode] ) - stream_.doConvertBuffer[mode] = true; - if ( stream_.userInterleaved != stream_.deviceInterleaved[mode] && - stream_.nUserChannels[mode] > 1 ) - stream_.doConvertBuffer[mode] = true; - - // Allocate the ApiHandle if necessary and then save. - AlsaHandle *apiInfo = 0; - if ( stream_.apiHandle == 0 ) { - try { - apiInfo = (AlsaHandle *) new AlsaHandle; - } - catch ( std::bad_alloc& ) { - errorText_ = "RtApiAlsa::probeDeviceOpen: error allocating AlsaHandle memory."; - goto error; - } - - if ( pthread_cond_init( &apiInfo->runnable_cv, NULL ) ) { - errorText_ = "RtApiAlsa::probeDeviceOpen: error initializing pthread condition variable."; - goto error; - } - - stream_.apiHandle = (void *) apiInfo; - apiInfo->handles[0] = 0; - apiInfo->handles[1] = 0; - } - else { - apiInfo = (AlsaHandle *) stream_.apiHandle; - } - apiInfo->handles[mode] = phandle; - phandle = 0; - - // Allocate necessary internal buffers. - unsigned long bufferBytes; - bufferBytes = stream_.nUserChannels[mode] * *bufferSize * formatBytes( stream_.userFormat ); - stream_.userBuffer[mode] = (char *) calloc( bufferBytes, 1 ); - if ( stream_.userBuffer[mode] == NULL ) { - errorText_ = "RtApiAlsa::probeDeviceOpen: error allocating user buffer memory."; - goto error; - } - - if ( stream_.doConvertBuffer[mode] ) { - - bool makeBuffer = true; - bufferBytes = stream_.nDeviceChannels[mode] * formatBytes( stream_.deviceFormat[mode] ); - if ( mode == INPUT ) { - if ( stream_.mode == OUTPUT && stream_.deviceBuffer ) { - unsigned long bytesOut = stream_.nDeviceChannels[0] * formatBytes( stream_.deviceFormat[0] ); - if ( bufferBytes <= bytesOut ) makeBuffer = false; - } - } - - if ( makeBuffer ) { - bufferBytes *= *bufferSize; - if ( stream_.deviceBuffer ) free( stream_.deviceBuffer ); - stream_.deviceBuffer = (char *) calloc( bufferBytes, 1 ); - if ( stream_.deviceBuffer == NULL ) { - errorText_ = "RtApiAlsa::probeDeviceOpen: error allocating device buffer memory."; - goto error; - } - } - } - - stream_.sampleRate = sampleRate; - stream_.nBuffers = periods; - stream_.device[mode] = device; - stream_.state = STREAM_STOPPED; - - // Setup the buffer conversion information structure. - if ( stream_.doConvertBuffer[mode] ) setConvertInfo( mode, firstChannel ); - - // Setup thread if necessary. - if ( stream_.mode == OUTPUT && mode == INPUT ) { - // We had already set up an output stream. - stream_.mode = DUPLEX; - // Link the streams if possible. - apiInfo->synchronized = false; - if ( snd_pcm_link( apiInfo->handles[0], apiInfo->handles[1] ) == 0 ) - apiInfo->synchronized = true; - else { - errorText_ = "RtApiAlsa::probeDeviceOpen: unable to synchronize input and output devices."; - error( RtAudioError::WARNING ); - } - } - else { - stream_.mode = mode; - - // Setup callback thread. - stream_.callbackInfo.object = (void *) this; - - // Set the thread attributes for joinable and realtime scheduling - // priority (optional). The higher priority will only take affect - // if the program is run as root or suid. Note, under Linux - // processes with CAP_SYS_NICE privilege, a user can change - // scheduling policy and priority (thus need not be root). See - // POSIX "capabilities". - pthread_attr_t attr; - pthread_attr_init( &attr ); - pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_JOINABLE ); - -#ifdef SCHED_RR // Undefined with some OSes (eg: NetBSD 1.6.x with GNU Pthread) - if ( options && options->flags & RTAUDIO_SCHEDULE_REALTIME ) { - // We previously attempted to increase the audio callback priority - // to SCHED_RR here via the attributes. However, while no errors - // were reported in doing so, it did not work. So, now this is - // done in the alsaCallbackHandler function. - stream_.callbackInfo.doRealtime = true; - int priority = options->priority; - int min = sched_get_priority_min( SCHED_RR ); - int max = sched_get_priority_max( SCHED_RR ); - if ( priority < min ) priority = min; - else if ( priority > max ) priority = max; - stream_.callbackInfo.priority = priority; - } -#endif - - stream_.callbackInfo.isRunning = true; - result = pthread_create( &stream_.callbackInfo.thread, &attr, alsaCallbackHandler, &stream_.callbackInfo ); - pthread_attr_destroy( &attr ); - if ( result ) { - stream_.callbackInfo.isRunning = false; - errorText_ = "RtApiAlsa::error creating callback thread!"; - goto error; - } - } - - return SUCCESS; - - error: - if ( apiInfo ) { - pthread_cond_destroy( &apiInfo->runnable_cv ); - if ( apiInfo->handles[0] ) snd_pcm_close( apiInfo->handles[0] ); - if ( apiInfo->handles[1] ) snd_pcm_close( apiInfo->handles[1] ); - delete apiInfo; - stream_.apiHandle = 0; - } - - if ( phandle) snd_pcm_close( phandle ); - - for ( int i=0; i<2; i++ ) { - if ( stream_.userBuffer[i] ) { - free( stream_.userBuffer[i] ); - stream_.userBuffer[i] = 0; - } - } - - if ( stream_.deviceBuffer ) { - free( stream_.deviceBuffer ); - stream_.deviceBuffer = 0; - } - - stream_.state = STREAM_CLOSED; - return FAILURE; -} - -void RtApiAlsa :: closeStream() -{ - if ( stream_.state == STREAM_CLOSED ) { - errorText_ = "RtApiAlsa::closeStream(): no open stream to close!"; - error( RtAudioError::WARNING ); - return; - } - - AlsaHandle *apiInfo = (AlsaHandle *) stream_.apiHandle; - stream_.callbackInfo.isRunning = false; - MUTEX_LOCK( &stream_.mutex ); - if ( stream_.state == STREAM_STOPPED ) { - apiInfo->runnable = true; - pthread_cond_signal( &apiInfo->runnable_cv ); - } - MUTEX_UNLOCK( &stream_.mutex ); - pthread_join( stream_.callbackInfo.thread, NULL ); - - if ( stream_.state == STREAM_RUNNING ) { - stream_.state = STREAM_STOPPED; - if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) - snd_pcm_drop( apiInfo->handles[0] ); - if ( stream_.mode == INPUT || stream_.mode == DUPLEX ) - snd_pcm_drop( apiInfo->handles[1] ); - } - - if ( apiInfo ) { - pthread_cond_destroy( &apiInfo->runnable_cv ); - if ( apiInfo->handles[0] ) snd_pcm_close( apiInfo->handles[0] ); - if ( apiInfo->handles[1] ) snd_pcm_close( apiInfo->handles[1] ); - delete apiInfo; - stream_.apiHandle = 0; - } - - for ( int i=0; i<2; i++ ) { - if ( stream_.userBuffer[i] ) { - free( stream_.userBuffer[i] ); - stream_.userBuffer[i] = 0; - } - } - - if ( stream_.deviceBuffer ) { - free( stream_.deviceBuffer ); - stream_.deviceBuffer = 0; - } - - stream_.mode = UNINITIALIZED; - stream_.state = STREAM_CLOSED; -} - -void RtApiAlsa :: startStream() -{ - // This method calls snd_pcm_prepare if the device isn't already in that state. - - verifyStream(); - if ( stream_.state == STREAM_RUNNING ) { - errorText_ = "RtApiAlsa::startStream(): the stream is already running!"; - error( RtAudioError::WARNING ); - return; - } - - MUTEX_LOCK( &stream_.mutex ); - - int result = 0; - snd_pcm_state_t state; - AlsaHandle *apiInfo = (AlsaHandle *) stream_.apiHandle; - snd_pcm_t **handle = (snd_pcm_t **) apiInfo->handles; - if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) { - state = snd_pcm_state( handle[0] ); - if ( state != SND_PCM_STATE_PREPARED ) { - result = snd_pcm_prepare( handle[0] ); - if ( result < 0 ) { - errorStream_ << "RtApiAlsa::startStream: error preparing output pcm device, " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - goto unlock; - } - } - } - - if ( ( stream_.mode == INPUT || stream_.mode == DUPLEX ) && !apiInfo->synchronized ) { - result = snd_pcm_drop(handle[1]); // fix to remove stale data received since device has been open - state = snd_pcm_state( handle[1] ); - if ( state != SND_PCM_STATE_PREPARED ) { - result = snd_pcm_prepare( handle[1] ); - if ( result < 0 ) { - errorStream_ << "RtApiAlsa::startStream: error preparing input pcm device, " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - goto unlock; - } - } - } - - stream_.state = STREAM_RUNNING; - - unlock: - apiInfo->runnable = true; - pthread_cond_signal( &apiInfo->runnable_cv ); - MUTEX_UNLOCK( &stream_.mutex ); - - if ( result >= 0 ) return; - error( RtAudioError::SYSTEM_ERROR ); -} - -void RtApiAlsa :: stopStream() -{ - verifyStream(); - if ( stream_.state == STREAM_STOPPED ) { - errorText_ = "RtApiAlsa::stopStream(): the stream is already stopped!"; - error( RtAudioError::WARNING ); - return; - } - - stream_.state = STREAM_STOPPED; - MUTEX_LOCK( &stream_.mutex ); - - int result = 0; - AlsaHandle *apiInfo = (AlsaHandle *) stream_.apiHandle; - snd_pcm_t **handle = (snd_pcm_t **) apiInfo->handles; - if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) { - if ( apiInfo->synchronized ) - result = snd_pcm_drop( handle[0] ); - else - result = snd_pcm_drain( handle[0] ); - if ( result < 0 ) { - errorStream_ << "RtApiAlsa::stopStream: error draining output pcm device, " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - goto unlock; - } - } - - if ( ( stream_.mode == INPUT || stream_.mode == DUPLEX ) && !apiInfo->synchronized ) { - result = snd_pcm_drop( handle[1] ); - if ( result < 0 ) { - errorStream_ << "RtApiAlsa::stopStream: error stopping input pcm device, " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - goto unlock; - } - } - - unlock: - apiInfo->runnable = false; // fixes high CPU usage when stopped - MUTEX_UNLOCK( &stream_.mutex ); - - if ( result >= 0 ) return; - error( RtAudioError::SYSTEM_ERROR ); -} - -void RtApiAlsa :: abortStream() -{ - verifyStream(); - if ( stream_.state == STREAM_STOPPED ) { - errorText_ = "RtApiAlsa::abortStream(): the stream is already stopped!"; - error( RtAudioError::WARNING ); - return; - } - - stream_.state = STREAM_STOPPED; - MUTEX_LOCK( &stream_.mutex ); - - int result = 0; - AlsaHandle *apiInfo = (AlsaHandle *) stream_.apiHandle; - snd_pcm_t **handle = (snd_pcm_t **) apiInfo->handles; - if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) { - result = snd_pcm_drop( handle[0] ); - if ( result < 0 ) { - errorStream_ << "RtApiAlsa::abortStream: error aborting output pcm device, " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - goto unlock; - } - } - - if ( ( stream_.mode == INPUT || stream_.mode == DUPLEX ) && !apiInfo->synchronized ) { - result = snd_pcm_drop( handle[1] ); - if ( result < 0 ) { - errorStream_ << "RtApiAlsa::abortStream: error aborting input pcm device, " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - goto unlock; - } - } - - unlock: - apiInfo->runnable = false; // fixes high CPU usage when stopped - MUTEX_UNLOCK( &stream_.mutex ); - - if ( result >= 0 ) return; - error( RtAudioError::SYSTEM_ERROR ); -} - -void RtApiAlsa :: callbackEvent() -{ - AlsaHandle *apiInfo = (AlsaHandle *) stream_.apiHandle; - if ( stream_.state == STREAM_STOPPED ) { - MUTEX_LOCK( &stream_.mutex ); - while ( !apiInfo->runnable ) - pthread_cond_wait( &apiInfo->runnable_cv, &stream_.mutex ); - - if ( stream_.state != STREAM_RUNNING ) { - MUTEX_UNLOCK( &stream_.mutex ); - return; - } - MUTEX_UNLOCK( &stream_.mutex ); - } - - if ( stream_.state == STREAM_CLOSED ) { - errorText_ = "RtApiAlsa::callbackEvent(): the stream is closed ... this shouldn't happen!"; - error( RtAudioError::WARNING ); - return; - } - - int doStopStream = 0; - RtAudioCallback callback = (RtAudioCallback) stream_.callbackInfo.callback; - double streamTime = getStreamTime(); - RtAudioStreamStatus status = 0; - if ( stream_.mode != INPUT && apiInfo->xrun[0] == true ) { - status |= RTAUDIO_OUTPUT_UNDERFLOW; - apiInfo->xrun[0] = false; - } - if ( stream_.mode != OUTPUT && apiInfo->xrun[1] == true ) { - status |= RTAUDIO_INPUT_OVERFLOW; - apiInfo->xrun[1] = false; - } - doStopStream = callback( stream_.userBuffer[0], stream_.userBuffer[1], - stream_.bufferSize, streamTime, status, stream_.callbackInfo.userData ); - - if ( doStopStream == 2 ) { - abortStream(); - return; - } - - MUTEX_LOCK( &stream_.mutex ); - - // The state might change while waiting on a mutex. - if ( stream_.state == STREAM_STOPPED ) goto unlock; - - int result; - char *buffer; - int channels; - snd_pcm_t **handle; - snd_pcm_sframes_t frames; - RtAudioFormat format; - handle = (snd_pcm_t **) apiInfo->handles; - - if ( stream_.mode == INPUT || stream_.mode == DUPLEX ) { - - // Setup parameters. - if ( stream_.doConvertBuffer[1] ) { - buffer = stream_.deviceBuffer; - channels = stream_.nDeviceChannels[1]; - format = stream_.deviceFormat[1]; - } - else { - buffer = stream_.userBuffer[1]; - channels = stream_.nUserChannels[1]; - format = stream_.userFormat; - } - - // Read samples from device in interleaved/non-interleaved format. - if ( stream_.deviceInterleaved[1] ) - result = snd_pcm_readi( handle[1], buffer, stream_.bufferSize ); - else { - void *bufs[channels]; - size_t offset = stream_.bufferSize * formatBytes( format ); - for ( int i=0; i<channels; i++ ) - bufs[i] = (void *) (buffer + (i * offset)); - result = snd_pcm_readn( handle[1], bufs, stream_.bufferSize ); - } - - if ( result < (int) stream_.bufferSize ) { - // Either an error or overrun occured. - if ( result == -EPIPE ) { - snd_pcm_state_t state = snd_pcm_state( handle[1] ); - if ( state == SND_PCM_STATE_XRUN ) { - apiInfo->xrun[1] = true; - result = snd_pcm_prepare( handle[1] ); - if ( result < 0 ) { - errorStream_ << "RtApiAlsa::callbackEvent: error preparing device after overrun, " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - } - } - else { - errorStream_ << "RtApiAlsa::callbackEvent: error, current state is " << snd_pcm_state_name( state ) << ", " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - } - } - else { - errorStream_ << "RtApiAlsa::callbackEvent: audio read error, " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - } - error( RtAudioError::WARNING ); - goto tryOutput; - } - - // Do byte swapping if necessary. - if ( stream_.doByteSwap[1] ) - byteSwapBuffer( buffer, stream_.bufferSize * channels, format ); - - // Do buffer conversion if necessary. - if ( stream_.doConvertBuffer[1] ) - convertBuffer( stream_.userBuffer[1], stream_.deviceBuffer, stream_.convertInfo[1] ); - - // Check stream latency - result = snd_pcm_delay( handle[1], &frames ); - if ( result == 0 && frames > 0 ) stream_.latency[1] = frames; - } - - tryOutput: - - if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) { - - // Setup parameters and do buffer conversion if necessary. - if ( stream_.doConvertBuffer[0] ) { - buffer = stream_.deviceBuffer; - convertBuffer( buffer, stream_.userBuffer[0], stream_.convertInfo[0] ); - channels = stream_.nDeviceChannels[0]; - format = stream_.deviceFormat[0]; - } - else { - buffer = stream_.userBuffer[0]; - channels = stream_.nUserChannels[0]; - format = stream_.userFormat; - } - - // Do byte swapping if necessary. - if ( stream_.doByteSwap[0] ) - byteSwapBuffer(buffer, stream_.bufferSize * channels, format); - - // Write samples to device in interleaved/non-interleaved format. - if ( stream_.deviceInterleaved[0] ) - result = snd_pcm_writei( handle[0], buffer, stream_.bufferSize ); - else { - void *bufs[channels]; - size_t offset = stream_.bufferSize * formatBytes( format ); - for ( int i=0; i<channels; i++ ) - bufs[i] = (void *) (buffer + (i * offset)); - result = snd_pcm_writen( handle[0], bufs, stream_.bufferSize ); - } - - if ( result < (int) stream_.bufferSize ) { - // Either an error or underrun occured. - if ( result == -EPIPE ) { - snd_pcm_state_t state = snd_pcm_state( handle[0] ); - if ( state == SND_PCM_STATE_XRUN ) { - apiInfo->xrun[0] = true; - result = snd_pcm_prepare( handle[0] ); - if ( result < 0 ) { - errorStream_ << "RtApiAlsa::callbackEvent: error preparing device after underrun, " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - } - else - errorText_ = "RtApiAlsa::callbackEvent: audio write error, underrun."; - } - else { - errorStream_ << "RtApiAlsa::callbackEvent: error, current state is " << snd_pcm_state_name( state ) << ", " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - } - } - else { - errorStream_ << "RtApiAlsa::callbackEvent: audio write error, " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - } - error( RtAudioError::WARNING ); - goto unlock; - } - - // Check stream latency - result = snd_pcm_delay( handle[0], &frames ); - if ( result == 0 && frames > 0 ) stream_.latency[0] = frames; - } - - unlock: - MUTEX_UNLOCK( &stream_.mutex ); - - RtApi::tickStreamTime(); - if ( doStopStream == 1 ) this->stopStream(); -} - -static void *alsaCallbackHandler( void *ptr ) -{ - CallbackInfo *info = (CallbackInfo *) ptr; - RtApiAlsa *object = (RtApiAlsa *) info->object; - bool *isRunning = &info->isRunning; - -#ifdef SCHED_RR // Undefined with some OSes (eg: NetBSD 1.6.x with GNU Pthread) - if ( info->doRealtime ) { - pthread_t tID = pthread_self(); // ID of this thread - sched_param prio = { info->priority }; // scheduling priority of thread - pthread_setschedparam( tID, SCHED_RR, &prio ); - } -#endif - - while ( *isRunning == true ) { - pthread_testcancel(); - object->callbackEvent(); - } - - pthread_exit( NULL ); -} - -//******************** End of __LINUX_ALSA__ *********************// -#endif - -#if defined(__LINUX_PULSE__) - -// Code written by Peter Meerwald, pmeerw@pmeerw.net -// and Tristan Matthews. - -#include <pulse/error.h> -#include <pulse/simple.h> -#include <cstdio> - -static const unsigned int SUPPORTED_SAMPLERATES[] = { 8000, 16000, 22050, 32000, - 44100, 48000, 96000, 0}; - -struct rtaudio_pa_format_mapping_t { - RtAudioFormat rtaudio_format; - pa_sample_format_t pa_format; -}; - -static const rtaudio_pa_format_mapping_t supported_sampleformats[] = { - {RTAUDIO_SINT16, PA_SAMPLE_S16LE}, - {RTAUDIO_SINT32, PA_SAMPLE_S32LE}, - {RTAUDIO_FLOAT32, PA_SAMPLE_FLOAT32LE}, - {0, PA_SAMPLE_INVALID}}; - -struct PulseAudioHandle { - pa_simple *s_play; - pa_simple *s_rec; - pthread_t thread; - pthread_cond_t runnable_cv; - bool runnable; - PulseAudioHandle() : s_play(0), s_rec(0), runnable(false) { } -}; - -RtApiPulse::~RtApiPulse() -{ - if ( stream_.state != STREAM_CLOSED ) - closeStream(); -} - -unsigned int RtApiPulse::getDeviceCount( void ) -{ - return 1; -} - -RtAudio::DeviceInfo RtApiPulse::getDeviceInfo( unsigned int /*device*/ ) -{ - RtAudio::DeviceInfo info; - info.probed = true; - info.name = "PulseAudio"; - info.outputChannels = 2; - info.inputChannels = 2; - info.duplexChannels = 2; - info.isDefaultOutput = true; - info.isDefaultInput = true; - - for ( const unsigned int *sr = SUPPORTED_SAMPLERATES; *sr; ++sr ) - info.sampleRates.push_back( *sr ); - - info.preferredSampleRate = 48000; - info.nativeFormats = RTAUDIO_SINT16 | RTAUDIO_SINT32 | RTAUDIO_FLOAT32; - - return info; -} - -static void *pulseaudio_callback( void * user ) -{ - CallbackInfo *cbi = static_cast<CallbackInfo *>( user ); - RtApiPulse *context = static_cast<RtApiPulse *>( cbi->object ); - volatile bool *isRunning = &cbi->isRunning; - - while ( *isRunning ) { - pthread_testcancel(); - context->callbackEvent(); - } - - pthread_exit( NULL ); -} - -void RtApiPulse::closeStream( void ) -{ - PulseAudioHandle *pah = static_cast<PulseAudioHandle *>( stream_.apiHandle ); - - stream_.callbackInfo.isRunning = false; - if ( pah ) { - MUTEX_LOCK( &stream_.mutex ); - if ( stream_.state == STREAM_STOPPED ) { - pah->runnable = true; - pthread_cond_signal( &pah->runnable_cv ); - } - MUTEX_UNLOCK( &stream_.mutex ); - - pthread_join( pah->thread, 0 ); - if ( pah->s_play ) { - pa_simple_flush( pah->s_play, NULL ); - pa_simple_free( pah->s_play ); - } - if ( pah->s_rec ) - pa_simple_free( pah->s_rec ); - - pthread_cond_destroy( &pah->runnable_cv ); - delete pah; - stream_.apiHandle = 0; - } - - if ( stream_.userBuffer[0] ) { - free( stream_.userBuffer[0] ); - stream_.userBuffer[0] = 0; - } - if ( stream_.userBuffer[1] ) { - free( stream_.userBuffer[1] ); - stream_.userBuffer[1] = 0; - } - - stream_.state = STREAM_CLOSED; - stream_.mode = UNINITIALIZED; -} - -void RtApiPulse::callbackEvent( void ) -{ - PulseAudioHandle *pah = static_cast<PulseAudioHandle *>( stream_.apiHandle ); - - if ( stream_.state == STREAM_STOPPED ) { - MUTEX_LOCK( &stream_.mutex ); - while ( !pah->runnable ) - pthread_cond_wait( &pah->runnable_cv, &stream_.mutex ); - - if ( stream_.state != STREAM_RUNNING ) { - MUTEX_UNLOCK( &stream_.mutex ); - return; - } - MUTEX_UNLOCK( &stream_.mutex ); - } - - if ( stream_.state == STREAM_CLOSED ) { - errorText_ = "RtApiPulse::callbackEvent(): the stream is closed ... " - "this shouldn't happen!"; - error( RtAudioError::WARNING ); - return; - } - - RtAudioCallback callback = (RtAudioCallback) stream_.callbackInfo.callback; - double streamTime = getStreamTime(); - RtAudioStreamStatus status = 0; - int doStopStream = callback( stream_.userBuffer[OUTPUT], stream_.userBuffer[INPUT], - stream_.bufferSize, streamTime, status, - stream_.callbackInfo.userData ); - - if ( doStopStream == 2 ) { - abortStream(); - return; - } - - MUTEX_LOCK( &stream_.mutex ); - void *pulse_in = stream_.doConvertBuffer[INPUT] ? stream_.deviceBuffer : stream_.userBuffer[INPUT]; - void *pulse_out = stream_.doConvertBuffer[OUTPUT] ? stream_.deviceBuffer : stream_.userBuffer[OUTPUT]; - - if ( stream_.state != STREAM_RUNNING ) - goto unlock; - - int pa_error; - size_t bytes; - if (stream_.mode == OUTPUT || stream_.mode == DUPLEX ) { - if ( stream_.doConvertBuffer[OUTPUT] ) { - convertBuffer( stream_.deviceBuffer, - stream_.userBuffer[OUTPUT], - stream_.convertInfo[OUTPUT] ); - bytes = stream_.nDeviceChannels[OUTPUT] * stream_.bufferSize * - formatBytes( stream_.deviceFormat[OUTPUT] ); - } else - bytes = stream_.nUserChannels[OUTPUT] * stream_.bufferSize * - formatBytes( stream_.userFormat ); - - if ( pa_simple_write( pah->s_play, pulse_out, bytes, &pa_error ) < 0 ) { - errorStream_ << "RtApiPulse::callbackEvent: audio write error, " << - pa_strerror( pa_error ) << "."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - } - } - - if ( stream_.mode == INPUT || stream_.mode == DUPLEX) { - if ( stream_.doConvertBuffer[INPUT] ) - bytes = stream_.nDeviceChannels[INPUT] * stream_.bufferSize * - formatBytes( stream_.deviceFormat[INPUT] ); - else - bytes = stream_.nUserChannels[INPUT] * stream_.bufferSize * - formatBytes( stream_.userFormat ); - - if ( pa_simple_read( pah->s_rec, pulse_in, bytes, &pa_error ) < 0 ) { - errorStream_ << "RtApiPulse::callbackEvent: audio read error, " << - pa_strerror( pa_error ) << "."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - } - if ( stream_.doConvertBuffer[INPUT] ) { - convertBuffer( stream_.userBuffer[INPUT], - stream_.deviceBuffer, - stream_.convertInfo[INPUT] ); - } - } - - unlock: - MUTEX_UNLOCK( &stream_.mutex ); - RtApi::tickStreamTime(); - - if ( doStopStream == 1 ) - stopStream(); -} - -void RtApiPulse::startStream( void ) -{ - PulseAudioHandle *pah = static_cast<PulseAudioHandle *>( stream_.apiHandle ); - - if ( stream_.state == STREAM_CLOSED ) { - errorText_ = "RtApiPulse::startStream(): the stream is not open!"; - error( RtAudioError::INVALID_USE ); - return; - } - if ( stream_.state == STREAM_RUNNING ) { - errorText_ = "RtApiPulse::startStream(): the stream is already running!"; - error( RtAudioError::WARNING ); - return; - } - - MUTEX_LOCK( &stream_.mutex ); - - stream_.state = STREAM_RUNNING; - - pah->runnable = true; - pthread_cond_signal( &pah->runnable_cv ); - MUTEX_UNLOCK( &stream_.mutex ); -} - -void RtApiPulse::stopStream( void ) -{ - PulseAudioHandle *pah = static_cast<PulseAudioHandle *>( stream_.apiHandle ); - - if ( stream_.state == STREAM_CLOSED ) { - errorText_ = "RtApiPulse::stopStream(): the stream is not open!"; - error( RtAudioError::INVALID_USE ); - return; - } - if ( stream_.state == STREAM_STOPPED ) { - errorText_ = "RtApiPulse::stopStream(): the stream is already stopped!"; - error( RtAudioError::WARNING ); - return; - } - - stream_.state = STREAM_STOPPED; - MUTEX_LOCK( &stream_.mutex ); - - if ( pah && pah->s_play ) { - int pa_error; - if ( pa_simple_drain( pah->s_play, &pa_error ) < 0 ) { - errorStream_ << "RtApiPulse::stopStream: error draining output device, " << - pa_strerror( pa_error ) << "."; - errorText_ = errorStream_.str(); - MUTEX_UNLOCK( &stream_.mutex ); - error( RtAudioError::SYSTEM_ERROR ); - return; - } - } - - stream_.state = STREAM_STOPPED; - MUTEX_UNLOCK( &stream_.mutex ); -} - -void RtApiPulse::abortStream( void ) -{ - PulseAudioHandle *pah = static_cast<PulseAudioHandle*>( stream_.apiHandle ); - - if ( stream_.state == STREAM_CLOSED ) { - errorText_ = "RtApiPulse::abortStream(): the stream is not open!"; - error( RtAudioError::INVALID_USE ); - return; - } - if ( stream_.state == STREAM_STOPPED ) { - errorText_ = "RtApiPulse::abortStream(): the stream is already stopped!"; - error( RtAudioError::WARNING ); - return; - } - - stream_.state = STREAM_STOPPED; - MUTEX_LOCK( &stream_.mutex ); - - if ( pah && pah->s_play ) { - int pa_error; - if ( pa_simple_flush( pah->s_play, &pa_error ) < 0 ) { - errorStream_ << "RtApiPulse::abortStream: error flushing output device, " << - pa_strerror( pa_error ) << "."; - errorText_ = errorStream_.str(); - MUTEX_UNLOCK( &stream_.mutex ); - error( RtAudioError::SYSTEM_ERROR ); - return; - } - } - - stream_.state = STREAM_STOPPED; - MUTEX_UNLOCK( &stream_.mutex ); -} - -bool RtApiPulse::probeDeviceOpen( unsigned int device, StreamMode mode, - unsigned int channels, unsigned int firstChannel, - unsigned int sampleRate, RtAudioFormat format, - unsigned int *bufferSize, RtAudio::StreamOptions *options ) -{ - PulseAudioHandle *pah = 0; - unsigned long bufferBytes = 0; - pa_sample_spec ss; - - if ( device != 0 ) return false; - if ( mode != INPUT && mode != OUTPUT ) return false; - if ( channels != 1 && channels != 2 ) { - errorText_ = "RtApiPulse::probeDeviceOpen: unsupported number of channels."; - return false; - } - ss.channels = channels; - - if ( firstChannel != 0 ) return false; - - bool sr_found = false; - for ( const unsigned int *sr = SUPPORTED_SAMPLERATES; *sr; ++sr ) { - if ( sampleRate == *sr ) { - sr_found = true; - stream_.sampleRate = sampleRate; - ss.rate = sampleRate; - break; - } - } - if ( !sr_found ) { - errorText_ = "RtApiPulse::probeDeviceOpen: unsupported sample rate."; - return false; - } - - bool sf_found = 0; - for ( const rtaudio_pa_format_mapping_t *sf = supported_sampleformats; - sf->rtaudio_format && sf->pa_format != PA_SAMPLE_INVALID; ++sf ) { - if ( format == sf->rtaudio_format ) { - sf_found = true; - stream_.userFormat = sf->rtaudio_format; - stream_.deviceFormat[mode] = stream_.userFormat; - ss.format = sf->pa_format; - break; - } - } - if ( !sf_found ) { // Use internal data format conversion. - stream_.userFormat = format; - stream_.deviceFormat[mode] = RTAUDIO_FLOAT32; - ss.format = PA_SAMPLE_FLOAT32LE; - } - - // Set other stream parameters. - if ( options && options->flags & RTAUDIO_NONINTERLEAVED ) stream_.userInterleaved = false; - else stream_.userInterleaved = true; - stream_.deviceInterleaved[mode] = true; - stream_.nBuffers = 1; - stream_.doByteSwap[mode] = false; - stream_.nUserChannels[mode] = channels; - stream_.nDeviceChannels[mode] = channels + firstChannel; - stream_.channelOffset[mode] = 0; - std::string streamName = "RtAudio"; - - // Set flags for buffer conversion. - stream_.doConvertBuffer[mode] = false; - if ( stream_.userFormat != stream_.deviceFormat[mode] ) - stream_.doConvertBuffer[mode] = true; - if ( stream_.nUserChannels[mode] < stream_.nDeviceChannels[mode] ) - stream_.doConvertBuffer[mode] = true; - - // Allocate necessary internal buffers. - bufferBytes = stream_.nUserChannels[mode] * *bufferSize * formatBytes( stream_.userFormat ); - stream_.userBuffer[mode] = (char *) calloc( bufferBytes, 1 ); - if ( stream_.userBuffer[mode] == NULL ) { - errorText_ = "RtApiPulse::probeDeviceOpen: error allocating user buffer memory."; - goto error; - } - stream_.bufferSize = *bufferSize; - - if ( stream_.doConvertBuffer[mode] ) { - - bool makeBuffer = true; - bufferBytes = stream_.nDeviceChannels[mode] * formatBytes( stream_.deviceFormat[mode] ); - if ( mode == INPUT ) { - if ( stream_.mode == OUTPUT && stream_.deviceBuffer ) { - unsigned long bytesOut = stream_.nDeviceChannels[0] * formatBytes( stream_.deviceFormat[0] ); - if ( bufferBytes <= bytesOut ) makeBuffer = false; - } - } - - if ( makeBuffer ) { - bufferBytes *= *bufferSize; - if ( stream_.deviceBuffer ) free( stream_.deviceBuffer ); - stream_.deviceBuffer = (char *) calloc( bufferBytes, 1 ); - if ( stream_.deviceBuffer == NULL ) { - errorText_ = "RtApiPulse::probeDeviceOpen: error allocating device buffer memory."; - goto error; - } - } - } - - stream_.device[mode] = device; - - // Setup the buffer conversion information structure. - if ( stream_.doConvertBuffer[mode] ) setConvertInfo( mode, firstChannel ); - - if ( !stream_.apiHandle ) { - PulseAudioHandle *pah = new PulseAudioHandle; - if ( !pah ) { - errorText_ = "RtApiPulse::probeDeviceOpen: error allocating memory for handle."; - goto error; - } - - stream_.apiHandle = pah; - if ( pthread_cond_init( &pah->runnable_cv, NULL ) != 0 ) { - errorText_ = "RtApiPulse::probeDeviceOpen: error creating condition variable."; - goto error; - } - } - pah = static_cast<PulseAudioHandle *>( stream_.apiHandle ); - - int error; - if ( options && !options->streamName.empty() ) streamName = options->streamName; - switch ( mode ) { - case INPUT: - pa_buffer_attr buffer_attr; - buffer_attr.fragsize = bufferBytes; - buffer_attr.maxlength = -1; - - pah->s_rec = pa_simple_new( NULL, streamName.c_str(), PA_STREAM_RECORD, NULL, "Record", &ss, NULL, &buffer_attr, &error ); - if ( !pah->s_rec ) { - errorText_ = "RtApiPulse::probeDeviceOpen: error connecting input to PulseAudio server."; - goto error; - } - break; - case OUTPUT: - pah->s_play = pa_simple_new( NULL, streamName.c_str(), PA_STREAM_PLAYBACK, NULL, "Playback", &ss, NULL, NULL, &error ); - if ( !pah->s_play ) { - errorText_ = "RtApiPulse::probeDeviceOpen: error connecting output to PulseAudio server."; - goto error; - } - break; - default: - goto error; - } - - if ( stream_.mode == UNINITIALIZED ) - stream_.mode = mode; - else if ( stream_.mode == mode ) - goto error; - else - stream_.mode = DUPLEX; - - if ( !stream_.callbackInfo.isRunning ) { - stream_.callbackInfo.object = this; - stream_.callbackInfo.isRunning = true; - if ( pthread_create( &pah->thread, NULL, pulseaudio_callback, (void *)&stream_.callbackInfo) != 0 ) { - errorText_ = "RtApiPulse::probeDeviceOpen: error creating thread."; - goto error; - } - } - - stream_.state = STREAM_STOPPED; - return true; - - error: - if ( pah && stream_.callbackInfo.isRunning ) { - pthread_cond_destroy( &pah->runnable_cv ); - delete pah; - stream_.apiHandle = 0; - } - - for ( int i=0; i<2; i++ ) { - if ( stream_.userBuffer[i] ) { - free( stream_.userBuffer[i] ); - stream_.userBuffer[i] = 0; - } - } - - if ( stream_.deviceBuffer ) { - free( stream_.deviceBuffer ); - stream_.deviceBuffer = 0; - } - - return FAILURE; -} - -//******************** End of __LINUX_PULSE__ *********************// -#endif - -#if defined(__LINUX_OSS__) - -#include <unistd.h> -#include <sys/ioctl.h> -#include <unistd.h> -#include <fcntl.h> -#include <sys/soundcard.h> -#include <errno.h> -#include <math.h> - -static void *ossCallbackHandler(void * ptr); - -// A structure to hold various information related to the OSS API -// implementation. -struct OssHandle { - int id[2]; // device ids - bool xrun[2]; - bool triggered; - pthread_cond_t runnable; - - OssHandle() - :triggered(false) { id[0] = 0; id[1] = 0; xrun[0] = false; xrun[1] = false; } -}; - -RtApiOss :: RtApiOss() -{ - // Nothing to do here. -} - -RtApiOss :: ~RtApiOss() -{ - if ( stream_.state != STREAM_CLOSED ) closeStream(); -} - -unsigned int RtApiOss :: getDeviceCount( void ) -{ - int mixerfd = open( "/dev/mixer", O_RDWR, 0 ); - if ( mixerfd == -1 ) { - errorText_ = "RtApiOss::getDeviceCount: error opening '/dev/mixer'."; - error( RtAudioError::WARNING ); - return 0; - } - - oss_sysinfo sysinfo; - if ( ioctl( mixerfd, SNDCTL_SYSINFO, &sysinfo ) == -1 ) { - close( mixerfd ); - errorText_ = "RtApiOss::getDeviceCount: error getting sysinfo, OSS version >= 4.0 is required."; - error( RtAudioError::WARNING ); - return 0; - } - - close( mixerfd ); - return sysinfo.numaudios; -} - -RtAudio::DeviceInfo RtApiOss :: getDeviceInfo( unsigned int device ) -{ - RtAudio::DeviceInfo info; - info.probed = false; - - int mixerfd = open( "/dev/mixer", O_RDWR, 0 ); - if ( mixerfd == -1 ) { - errorText_ = "RtApiOss::getDeviceInfo: error opening '/dev/mixer'."; - error( RtAudioError::WARNING ); - return info; - } - - oss_sysinfo sysinfo; - int result = ioctl( mixerfd, SNDCTL_SYSINFO, &sysinfo ); - if ( result == -1 ) { - close( mixerfd ); - errorText_ = "RtApiOss::getDeviceInfo: error getting sysinfo, OSS version >= 4.0 is required."; - error( RtAudioError::WARNING ); - return info; - } - - unsigned nDevices = sysinfo.numaudios; - if ( nDevices == 0 ) { - close( mixerfd ); - errorText_ = "RtApiOss::getDeviceInfo: no devices found!"; - error( RtAudioError::INVALID_USE ); - return info; - } - - if ( device >= nDevices ) { - close( mixerfd ); - errorText_ = "RtApiOss::getDeviceInfo: device ID is invalid!"; - error( RtAudioError::INVALID_USE ); - return info; - } - - oss_audioinfo ainfo; - ainfo.dev = device; - result = ioctl( mixerfd, SNDCTL_AUDIOINFO, &ainfo ); - close( mixerfd ); - if ( result == -1 ) { - errorStream_ << "RtApiOss::getDeviceInfo: error getting device (" << ainfo.name << ") info."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - return info; - } - - // Probe channels - if ( ainfo.caps & PCM_CAP_OUTPUT ) info.outputChannels = ainfo.max_channels; - if ( ainfo.caps & PCM_CAP_INPUT ) info.inputChannels = ainfo.max_channels; - if ( ainfo.caps & PCM_CAP_DUPLEX ) { - if ( info.outputChannels > 0 && info.inputChannels > 0 && ainfo.caps & PCM_CAP_DUPLEX ) - info.duplexChannels = (info.outputChannels > info.inputChannels) ? info.inputChannels : info.outputChannels; - } - - // Probe data formats ... do for input - unsigned long mask = ainfo.iformats; - if ( mask & AFMT_S16_LE || mask & AFMT_S16_BE ) - info.nativeFormats |= RTAUDIO_SINT16; - if ( mask & AFMT_S8 ) - info.nativeFormats |= RTAUDIO_SINT8; - if ( mask & AFMT_S32_LE || mask & AFMT_S32_BE ) - info.nativeFormats |= RTAUDIO_SINT32; - if ( mask & AFMT_FLOAT ) - info.nativeFormats |= RTAUDIO_FLOAT32; - if ( mask & AFMT_S24_LE || mask & AFMT_S24_BE ) - info.nativeFormats |= RTAUDIO_SINT24; - - // Check that we have at least one supported format - if ( info.nativeFormats == 0 ) { - errorStream_ << "RtApiOss::getDeviceInfo: device (" << ainfo.name << ") data format not supported by RtAudio."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - return info; - } - - // Probe the supported sample rates. - info.sampleRates.clear(); - if ( ainfo.nrates ) { - for ( unsigned int i=0; i<ainfo.nrates; i++ ) { - for ( unsigned int k=0; k<MAX_SAMPLE_RATES; k++ ) { - if ( ainfo.rates[i] == SAMPLE_RATES[k] ) { - info.sampleRates.push_back( SAMPLE_RATES[k] ); - - if ( !info.preferredSampleRate || ( SAMPLE_RATES[k] <= 48000 && SAMPLE_RATES[k] > info.preferredSampleRate ) ) - info.preferredSampleRate = SAMPLE_RATES[k]; - - break; - } - } - } - } - else { - // Check min and max rate values; - for ( unsigned int k=0; k<MAX_SAMPLE_RATES; k++ ) { - if ( ainfo.min_rate <= (int) SAMPLE_RATES[k] && ainfo.max_rate >= (int) SAMPLE_RATES[k] ) { - info.sampleRates.push_back( SAMPLE_RATES[k] ); - - if ( !info.preferredSampleRate || ( SAMPLE_RATES[k] <= 48000 && SAMPLE_RATES[k] > info.preferredSampleRate ) ) - info.preferredSampleRate = SAMPLE_RATES[k]; - } - } - } - - if ( info.sampleRates.size() == 0 ) { - errorStream_ << "RtApiOss::getDeviceInfo: no supported sample rates found for device (" << ainfo.name << ")."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - } - else { - info.probed = true; - info.name = ainfo.name; - } - - return info; -} - - -bool RtApiOss :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, - unsigned int firstChannel, unsigned int sampleRate, - RtAudioFormat format, unsigned int *bufferSize, - RtAudio::StreamOptions *options ) -{ - int mixerfd = open( "/dev/mixer", O_RDWR, 0 ); - if ( mixerfd == -1 ) { - errorText_ = "RtApiOss::probeDeviceOpen: error opening '/dev/mixer'."; - return FAILURE; - } - - oss_sysinfo sysinfo; - int result = ioctl( mixerfd, SNDCTL_SYSINFO, &sysinfo ); - if ( result == -1 ) { - close( mixerfd ); - errorText_ = "RtApiOss::probeDeviceOpen: error getting sysinfo, OSS version >= 4.0 is required."; - return FAILURE; - } - - unsigned nDevices = sysinfo.numaudios; - if ( nDevices == 0 ) { - // This should not happen because a check is made before this function is called. - close( mixerfd ); - errorText_ = "RtApiOss::probeDeviceOpen: no devices found!"; - return FAILURE; - } - - if ( device >= nDevices ) { - // This should not happen because a check is made before this function is called. - close( mixerfd ); - errorText_ = "RtApiOss::probeDeviceOpen: device ID is invalid!"; - return FAILURE; - } - - oss_audioinfo ainfo; - ainfo.dev = device; - result = ioctl( mixerfd, SNDCTL_AUDIOINFO, &ainfo ); - close( mixerfd ); - if ( result == -1 ) { - errorStream_ << "RtApiOss::getDeviceInfo: error getting device (" << ainfo.name << ") info."; - errorText_ = errorStream_.str(); - return FAILURE; - } - - // Check if device supports input or output - if ( ( mode == OUTPUT && !( ainfo.caps & PCM_CAP_OUTPUT ) ) || - ( mode == INPUT && !( ainfo.caps & PCM_CAP_INPUT ) ) ) { - if ( mode == OUTPUT ) - errorStream_ << "RtApiOss::probeDeviceOpen: device (" << ainfo.name << ") does not support output."; - else - errorStream_ << "RtApiOss::probeDeviceOpen: device (" << ainfo.name << ") does not support input."; - errorText_ = errorStream_.str(); - return FAILURE; - } - - int flags = 0; - OssHandle *handle = (OssHandle *) stream_.apiHandle; - if ( mode == OUTPUT ) - flags |= O_WRONLY; - else { // mode == INPUT - if (stream_.mode == OUTPUT && stream_.device[0] == device) { - // We just set the same device for playback ... close and reopen for duplex (OSS only). - close( handle->id[0] ); - handle->id[0] = 0; - if ( !( ainfo.caps & PCM_CAP_DUPLEX ) ) { - errorStream_ << "RtApiOss::probeDeviceOpen: device (" << ainfo.name << ") does not support duplex mode."; - errorText_ = errorStream_.str(); - return FAILURE; - } - // Check that the number previously set channels is the same. - if ( stream_.nUserChannels[0] != channels ) { - errorStream_ << "RtApiOss::probeDeviceOpen: input/output channels must be equal for OSS duplex device (" << ainfo.name << ")."; - errorText_ = errorStream_.str(); - return FAILURE; - } - flags |= O_RDWR; - } - else - flags |= O_RDONLY; - } - - // Set exclusive access if specified. - if ( options && options->flags & RTAUDIO_HOG_DEVICE ) flags |= O_EXCL; - - // Try to open the device. - int fd; - fd = open( ainfo.devnode, flags, 0 ); - if ( fd == -1 ) { - if ( errno == EBUSY ) - errorStream_ << "RtApiOss::probeDeviceOpen: device (" << ainfo.name << ") is busy."; - else - errorStream_ << "RtApiOss::probeDeviceOpen: error opening device (" << ainfo.name << ")."; - errorText_ = errorStream_.str(); - return FAILURE; - } - - // For duplex operation, specifically set this mode (this doesn't seem to work). - /* - if ( flags | O_RDWR ) { - result = ioctl( fd, SNDCTL_DSP_SETDUPLEX, NULL ); - if ( result == -1) { - errorStream_ << "RtApiOss::probeDeviceOpen: error setting duplex mode for device (" << ainfo.name << ")."; - errorText_ = errorStream_.str(); - return FAILURE; - } - } - */ - - // Check the device channel support. - stream_.nUserChannels[mode] = channels; - if ( ainfo.max_channels < (int)(channels + firstChannel) ) { - close( fd ); - errorStream_ << "RtApiOss::probeDeviceOpen: the device (" << ainfo.name << ") does not support requested channel parameters."; - errorText_ = errorStream_.str(); - return FAILURE; - } - - // Set the number of channels. - int deviceChannels = channels + firstChannel; - result = ioctl( fd, SNDCTL_DSP_CHANNELS, &deviceChannels ); - if ( result == -1 || deviceChannels < (int)(channels + firstChannel) ) { - close( fd ); - errorStream_ << "RtApiOss::probeDeviceOpen: error setting channel parameters on device (" << ainfo.name << ")."; - errorText_ = errorStream_.str(); - return FAILURE; - } - stream_.nDeviceChannels[mode] = deviceChannels; - - // Get the data format mask - int mask; - result = ioctl( fd, SNDCTL_DSP_GETFMTS, &mask ); - if ( result == -1 ) { - close( fd ); - errorStream_ << "RtApiOss::probeDeviceOpen: error getting device (" << ainfo.name << ") data formats."; - errorText_ = errorStream_.str(); - return FAILURE; - } - - // Determine how to set the device format. - stream_.userFormat = format; - int deviceFormat = -1; - stream_.doByteSwap[mode] = false; - if ( format == RTAUDIO_SINT8 ) { - if ( mask & AFMT_S8 ) { - deviceFormat = AFMT_S8; - stream_.deviceFormat[mode] = RTAUDIO_SINT8; - } - } - else if ( format == RTAUDIO_SINT16 ) { - if ( mask & AFMT_S16_NE ) { - deviceFormat = AFMT_S16_NE; - stream_.deviceFormat[mode] = RTAUDIO_SINT16; - } - else if ( mask & AFMT_S16_OE ) { - deviceFormat = AFMT_S16_OE; - stream_.deviceFormat[mode] = RTAUDIO_SINT16; - stream_.doByteSwap[mode] = true; - } - } - else if ( format == RTAUDIO_SINT24 ) { - if ( mask & AFMT_S24_NE ) { - deviceFormat = AFMT_S24_NE; - stream_.deviceFormat[mode] = RTAUDIO_SINT24; - } - else if ( mask & AFMT_S24_OE ) { - deviceFormat = AFMT_S24_OE; - stream_.deviceFormat[mode] = RTAUDIO_SINT24; - stream_.doByteSwap[mode] = true; - } - } - else if ( format == RTAUDIO_SINT32 ) { - if ( mask & AFMT_S32_NE ) { - deviceFormat = AFMT_S32_NE; - stream_.deviceFormat[mode] = RTAUDIO_SINT32; - } - else if ( mask & AFMT_S32_OE ) { - deviceFormat = AFMT_S32_OE; - stream_.deviceFormat[mode] = RTAUDIO_SINT32; - stream_.doByteSwap[mode] = true; - } - } - - if ( deviceFormat == -1 ) { - // The user requested format is not natively supported by the device. - if ( mask & AFMT_S16_NE ) { - deviceFormat = AFMT_S16_NE; - stream_.deviceFormat[mode] = RTAUDIO_SINT16; - } - else if ( mask & AFMT_S32_NE ) { - deviceFormat = AFMT_S32_NE; - stream_.deviceFormat[mode] = RTAUDIO_SINT32; - } - else if ( mask & AFMT_S24_NE ) { - deviceFormat = AFMT_S24_NE; - stream_.deviceFormat[mode] = RTAUDIO_SINT24; - } - else if ( mask & AFMT_S16_OE ) { - deviceFormat = AFMT_S16_OE; - stream_.deviceFormat[mode] = RTAUDIO_SINT16; - stream_.doByteSwap[mode] = true; - } - else if ( mask & AFMT_S32_OE ) { - deviceFormat = AFMT_S32_OE; - stream_.deviceFormat[mode] = RTAUDIO_SINT32; - stream_.doByteSwap[mode] = true; - } - else if ( mask & AFMT_S24_OE ) { - deviceFormat = AFMT_S24_OE; - stream_.deviceFormat[mode] = RTAUDIO_SINT24; - stream_.doByteSwap[mode] = true; - } - else if ( mask & AFMT_S8) { - deviceFormat = AFMT_S8; - stream_.deviceFormat[mode] = RTAUDIO_SINT8; - } - } - - if ( stream_.deviceFormat[mode] == 0 ) { - // This really shouldn't happen ... - close( fd ); - errorStream_ << "RtApiOss::probeDeviceOpen: device (" << ainfo.name << ") data format not supported by RtAudio."; - errorText_ = errorStream_.str(); - return FAILURE; - } - - // Set the data format. - int temp = deviceFormat; - result = ioctl( fd, SNDCTL_DSP_SETFMT, &deviceFormat ); - if ( result == -1 || deviceFormat != temp ) { - close( fd ); - errorStream_ << "RtApiOss::probeDeviceOpen: error setting data format on device (" << ainfo.name << ")."; - errorText_ = errorStream_.str(); - return FAILURE; - } - - // Attempt to set the buffer size. According to OSS, the minimum - // number of buffers is two. The supposed minimum buffer size is 16 - // bytes, so that will be our lower bound. The argument to this - // call is in the form 0xMMMMSSSS (hex), where the buffer size (in - // bytes) is given as 2^SSSS and the number of buffers as 2^MMMM. - // We'll check the actual value used near the end of the setup - // procedure. - int ossBufferBytes = *bufferSize * formatBytes( stream_.deviceFormat[mode] ) * deviceChannels; - if ( ossBufferBytes < 16 ) ossBufferBytes = 16; - int buffers = 0; - if ( options ) buffers = options->numberOfBuffers; - if ( options && options->flags & RTAUDIO_MINIMIZE_LATENCY ) buffers = 2; - if ( buffers < 2 ) buffers = 3; - temp = ((int) buffers << 16) + (int)( log10( (double)ossBufferBytes ) / log10( 2.0 ) ); - result = ioctl( fd, SNDCTL_DSP_SETFRAGMENT, &temp ); - if ( result == -1 ) { - close( fd ); - errorStream_ << "RtApiOss::probeDeviceOpen: error setting buffer size on device (" << ainfo.name << ")."; - errorText_ = errorStream_.str(); - return FAILURE; - } - stream_.nBuffers = buffers; - - // Save buffer size (in sample frames). - *bufferSize = ossBufferBytes / ( formatBytes(stream_.deviceFormat[mode]) * deviceChannels ); - stream_.bufferSize = *bufferSize; - - // Set the sample rate. - int srate = sampleRate; - result = ioctl( fd, SNDCTL_DSP_SPEED, &srate ); - if ( result == -1 ) { - close( fd ); - errorStream_ << "RtApiOss::probeDeviceOpen: error setting sample rate (" << sampleRate << ") on device (" << ainfo.name << ")."; - errorText_ = errorStream_.str(); - return FAILURE; - } - - // Verify the sample rate setup worked. - if ( abs( srate - sampleRate ) > 100 ) { - close( fd ); - errorStream_ << "RtApiOss::probeDeviceOpen: device (" << ainfo.name << ") does not support sample rate (" << sampleRate << ")."; - errorText_ = errorStream_.str(); - return FAILURE; - } - stream_.sampleRate = sampleRate; - - if ( mode == INPUT && stream_.mode == OUTPUT && stream_.device[0] == device) { - // We're doing duplex setup here. - stream_.deviceFormat[0] = stream_.deviceFormat[1]; - stream_.nDeviceChannels[0] = deviceChannels; - } - - // Set interleaving parameters. - stream_.userInterleaved = true; - stream_.deviceInterleaved[mode] = true; - if ( options && options->flags & RTAUDIO_NONINTERLEAVED ) - stream_.userInterleaved = false; - - // Set flags for buffer conversion - stream_.doConvertBuffer[mode] = false; - if ( stream_.userFormat != stream_.deviceFormat[mode] ) - stream_.doConvertBuffer[mode] = true; - if ( stream_.nUserChannels[mode] < stream_.nDeviceChannels[mode] ) - stream_.doConvertBuffer[mode] = true; - if ( stream_.userInterleaved != stream_.deviceInterleaved[mode] && - stream_.nUserChannels[mode] > 1 ) - stream_.doConvertBuffer[mode] = true; - - // Allocate the stream handles if necessary and then save. - if ( stream_.apiHandle == 0 ) { - try { - handle = new OssHandle; - } - catch ( std::bad_alloc& ) { - errorText_ = "RtApiOss::probeDeviceOpen: error allocating OssHandle memory."; - goto error; - } - - if ( pthread_cond_init( &handle->runnable, NULL ) ) { - errorText_ = "RtApiOss::probeDeviceOpen: error initializing pthread condition variable."; - goto error; - } - - stream_.apiHandle = (void *) handle; - } - else { - handle = (OssHandle *) stream_.apiHandle; - } - handle->id[mode] = fd; - - // Allocate necessary internal buffers. - unsigned long bufferBytes; - bufferBytes = stream_.nUserChannels[mode] * *bufferSize * formatBytes( stream_.userFormat ); - stream_.userBuffer[mode] = (char *) calloc( bufferBytes, 1 ); - if ( stream_.userBuffer[mode] == NULL ) { - errorText_ = "RtApiOss::probeDeviceOpen: error allocating user buffer memory."; - goto error; - } - - if ( stream_.doConvertBuffer[mode] ) { - - bool makeBuffer = true; - bufferBytes = stream_.nDeviceChannels[mode] * formatBytes( stream_.deviceFormat[mode] ); - if ( mode == INPUT ) { - if ( stream_.mode == OUTPUT && stream_.deviceBuffer ) { - unsigned long bytesOut = stream_.nDeviceChannels[0] * formatBytes( stream_.deviceFormat[0] ); - if ( bufferBytes <= bytesOut ) makeBuffer = false; - } - } - - if ( makeBuffer ) { - bufferBytes *= *bufferSize; - if ( stream_.deviceBuffer ) free( stream_.deviceBuffer ); - stream_.deviceBuffer = (char *) calloc( bufferBytes, 1 ); - if ( stream_.deviceBuffer == NULL ) { - errorText_ = "RtApiOss::probeDeviceOpen: error allocating device buffer memory."; - goto error; - } - } - } - - stream_.device[mode] = device; - stream_.state = STREAM_STOPPED; - - // Setup the buffer conversion information structure. - if ( stream_.doConvertBuffer[mode] ) setConvertInfo( mode, firstChannel ); - - // Setup thread if necessary. - if ( stream_.mode == OUTPUT && mode == INPUT ) { - // We had already set up an output stream. - stream_.mode = DUPLEX; - if ( stream_.device[0] == device ) handle->id[0] = fd; - } - else { - stream_.mode = mode; - - // Setup callback thread. - stream_.callbackInfo.object = (void *) this; - - // Set the thread attributes for joinable and realtime scheduling - // priority. The higher priority will only take affect if the - // program is run as root or suid. - pthread_attr_t attr; - pthread_attr_init( &attr ); - pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_JOINABLE ); -#ifdef SCHED_RR // Undefined with some OSes (eg: NetBSD 1.6.x with GNU Pthread) - if ( options && options->flags & RTAUDIO_SCHEDULE_REALTIME ) { - struct sched_param param; - int priority = options->priority; - int min = sched_get_priority_min( SCHED_RR ); - int max = sched_get_priority_max( SCHED_RR ); - if ( priority < min ) priority = min; - else if ( priority > max ) priority = max; - param.sched_priority = priority; - pthread_attr_setschedparam( &attr, ¶m ); - pthread_attr_setschedpolicy( &attr, SCHED_RR ); - } - else - pthread_attr_setschedpolicy( &attr, SCHED_OTHER ); -#else - pthread_attr_setschedpolicy( &attr, SCHED_OTHER ); -#endif - - stream_.callbackInfo.isRunning = true; - result = pthread_create( &stream_.callbackInfo.thread, &attr, ossCallbackHandler, &stream_.callbackInfo ); - pthread_attr_destroy( &attr ); - if ( result ) { - stream_.callbackInfo.isRunning = false; - errorText_ = "RtApiOss::error creating callback thread!"; - goto error; - } - } - - return SUCCESS; - - error: - if ( handle ) { - pthread_cond_destroy( &handle->runnable ); - if ( handle->id[0] ) close( handle->id[0] ); - if ( handle->id[1] ) close( handle->id[1] ); - delete handle; - stream_.apiHandle = 0; - } - - for ( int i=0; i<2; i++ ) { - if ( stream_.userBuffer[i] ) { - free( stream_.userBuffer[i] ); - stream_.userBuffer[i] = 0; - } - } - - if ( stream_.deviceBuffer ) { - free( stream_.deviceBuffer ); - stream_.deviceBuffer = 0; - } - - return FAILURE; -} - -void RtApiOss :: closeStream() -{ - if ( stream_.state == STREAM_CLOSED ) { - errorText_ = "RtApiOss::closeStream(): no open stream to close!"; - error( RtAudioError::WARNING ); - return; - } - - OssHandle *handle = (OssHandle *) stream_.apiHandle; - stream_.callbackInfo.isRunning = false; - MUTEX_LOCK( &stream_.mutex ); - if ( stream_.state == STREAM_STOPPED ) - pthread_cond_signal( &handle->runnable ); - MUTEX_UNLOCK( &stream_.mutex ); - pthread_join( stream_.callbackInfo.thread, NULL ); - - if ( stream_.state == STREAM_RUNNING ) { - if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) - ioctl( handle->id[0], SNDCTL_DSP_HALT, 0 ); - else - ioctl( handle->id[1], SNDCTL_DSP_HALT, 0 ); - stream_.state = STREAM_STOPPED; - } - - if ( handle ) { - pthread_cond_destroy( &handle->runnable ); - if ( handle->id[0] ) close( handle->id[0] ); - if ( handle->id[1] ) close( handle->id[1] ); - delete handle; - stream_.apiHandle = 0; - } - - for ( int i=0; i<2; i++ ) { - if ( stream_.userBuffer[i] ) { - free( stream_.userBuffer[i] ); - stream_.userBuffer[i] = 0; - } - } - - if ( stream_.deviceBuffer ) { - free( stream_.deviceBuffer ); - stream_.deviceBuffer = 0; - } - - stream_.mode = UNINITIALIZED; - stream_.state = STREAM_CLOSED; -} - -void RtApiOss :: startStream() -{ - verifyStream(); - if ( stream_.state == STREAM_RUNNING ) { - errorText_ = "RtApiOss::startStream(): the stream is already running!"; - error( RtAudioError::WARNING ); - return; - } - - MUTEX_LOCK( &stream_.mutex ); - - stream_.state = STREAM_RUNNING; - - // No need to do anything else here ... OSS automatically starts - // when fed samples. - - MUTEX_UNLOCK( &stream_.mutex ); - - OssHandle *handle = (OssHandle *) stream_.apiHandle; - pthread_cond_signal( &handle->runnable ); -} - -void RtApiOss :: stopStream() -{ - verifyStream(); - if ( stream_.state == STREAM_STOPPED ) { - errorText_ = "RtApiOss::stopStream(): the stream is already stopped!"; - error( RtAudioError::WARNING ); - return; - } - - MUTEX_LOCK( &stream_.mutex ); - - // The state might change while waiting on a mutex. - if ( stream_.state == STREAM_STOPPED ) { - MUTEX_UNLOCK( &stream_.mutex ); - return; - } - - int result = 0; - OssHandle *handle = (OssHandle *) stream_.apiHandle; - if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) { - - // Flush the output with zeros a few times. - char *buffer; - int samples; - RtAudioFormat format; - - if ( stream_.doConvertBuffer[0] ) { - buffer = stream_.deviceBuffer; - samples = stream_.bufferSize * stream_.nDeviceChannels[0]; - format = stream_.deviceFormat[0]; - } - else { - buffer = stream_.userBuffer[0]; - samples = stream_.bufferSize * stream_.nUserChannels[0]; - format = stream_.userFormat; - } - - memset( buffer, 0, samples * formatBytes(format) ); - for ( unsigned int i=0; i<stream_.nBuffers+1; i++ ) { - result = write( handle->id[0], buffer, samples * formatBytes(format) ); - if ( result == -1 ) { - errorText_ = "RtApiOss::stopStream: audio write error."; - error( RtAudioError::WARNING ); - } - } - - result = ioctl( handle->id[0], SNDCTL_DSP_HALT, 0 ); - if ( result == -1 ) { - errorStream_ << "RtApiOss::stopStream: system error stopping callback procedure on device (" << stream_.device[0] << ")."; - errorText_ = errorStream_.str(); - goto unlock; - } - handle->triggered = false; - } - - if ( stream_.mode == INPUT || ( stream_.mode == DUPLEX && handle->id[0] != handle->id[1] ) ) { - result = ioctl( handle->id[1], SNDCTL_DSP_HALT, 0 ); - if ( result == -1 ) { - errorStream_ << "RtApiOss::stopStream: system error stopping input callback procedure on device (" << stream_.device[0] << ")."; - errorText_ = errorStream_.str(); - goto unlock; - } - } - - unlock: - stream_.state = STREAM_STOPPED; - MUTEX_UNLOCK( &stream_.mutex ); - - if ( result != -1 ) return; - error( RtAudioError::SYSTEM_ERROR ); -} - -void RtApiOss :: abortStream() -{ - verifyStream(); - if ( stream_.state == STREAM_STOPPED ) { - errorText_ = "RtApiOss::abortStream(): the stream is already stopped!"; - error( RtAudioError::WARNING ); - return; - } - - MUTEX_LOCK( &stream_.mutex ); - - // The state might change while waiting on a mutex. - if ( stream_.state == STREAM_STOPPED ) { - MUTEX_UNLOCK( &stream_.mutex ); - return; - } - - int result = 0; - OssHandle *handle = (OssHandle *) stream_.apiHandle; - if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) { - result = ioctl( handle->id[0], SNDCTL_DSP_HALT, 0 ); - if ( result == -1 ) { - errorStream_ << "RtApiOss::abortStream: system error stopping callback procedure on device (" << stream_.device[0] << ")."; - errorText_ = errorStream_.str(); - goto unlock; - } - handle->triggered = false; - } - - if ( stream_.mode == INPUT || ( stream_.mode == DUPLEX && handle->id[0] != handle->id[1] ) ) { - result = ioctl( handle->id[1], SNDCTL_DSP_HALT, 0 ); - if ( result == -1 ) { - errorStream_ << "RtApiOss::abortStream: system error stopping input callback procedure on device (" << stream_.device[0] << ")."; - errorText_ = errorStream_.str(); - goto unlock; - } - } - - unlock: - stream_.state = STREAM_STOPPED; - MUTEX_UNLOCK( &stream_.mutex ); - - if ( result != -1 ) return; - error( RtAudioError::SYSTEM_ERROR ); -} - -void RtApiOss :: callbackEvent() -{ - OssHandle *handle = (OssHandle *) stream_.apiHandle; - if ( stream_.state == STREAM_STOPPED ) { - MUTEX_LOCK( &stream_.mutex ); - pthread_cond_wait( &handle->runnable, &stream_.mutex ); - if ( stream_.state != STREAM_RUNNING ) { - MUTEX_UNLOCK( &stream_.mutex ); - return; - } - MUTEX_UNLOCK( &stream_.mutex ); - } - - if ( stream_.state == STREAM_CLOSED ) { - errorText_ = "RtApiOss::callbackEvent(): the stream is closed ... this shouldn't happen!"; - error( RtAudioError::WARNING ); - return; - } - - // Invoke user callback to get fresh output data. - int doStopStream = 0; - RtAudioCallback callback = (RtAudioCallback) stream_.callbackInfo.callback; - double streamTime = getStreamTime(); - RtAudioStreamStatus status = 0; - if ( stream_.mode != INPUT && handle->xrun[0] == true ) { - status |= RTAUDIO_OUTPUT_UNDERFLOW; - handle->xrun[0] = false; - } - if ( stream_.mode != OUTPUT && handle->xrun[1] == true ) { - status |= RTAUDIO_INPUT_OVERFLOW; - handle->xrun[1] = false; - } - doStopStream = callback( stream_.userBuffer[0], stream_.userBuffer[1], - stream_.bufferSize, streamTime, status, stream_.callbackInfo.userData ); - if ( doStopStream == 2 ) { - this->abortStream(); - return; - } - - MUTEX_LOCK( &stream_.mutex ); - - // The state might change while waiting on a mutex. - if ( stream_.state == STREAM_STOPPED ) goto unlock; - - int result; - char *buffer; - int samples; - RtAudioFormat format; - - if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) { - - // Setup parameters and do buffer conversion if necessary. - if ( stream_.doConvertBuffer[0] ) { - buffer = stream_.deviceBuffer; - convertBuffer( buffer, stream_.userBuffer[0], stream_.convertInfo[0] ); - samples = stream_.bufferSize * stream_.nDeviceChannels[0]; - format = stream_.deviceFormat[0]; - } - else { - buffer = stream_.userBuffer[0]; - samples = stream_.bufferSize * stream_.nUserChannels[0]; - format = stream_.userFormat; - } - - // Do byte swapping if necessary. - if ( stream_.doByteSwap[0] ) - byteSwapBuffer( buffer, samples, format ); - - if ( stream_.mode == DUPLEX && handle->triggered == false ) { - int trig = 0; - ioctl( handle->id[0], SNDCTL_DSP_SETTRIGGER, &trig ); - result = write( handle->id[0], buffer, samples * formatBytes(format) ); - trig = PCM_ENABLE_INPUT|PCM_ENABLE_OUTPUT; - ioctl( handle->id[0], SNDCTL_DSP_SETTRIGGER, &trig ); - handle->triggered = true; - } - else - // Write samples to device. - result = write( handle->id[0], buffer, samples * formatBytes(format) ); - - if ( result == -1 ) { - // We'll assume this is an underrun, though there isn't a - // specific means for determining that. - handle->xrun[0] = true; - errorText_ = "RtApiOss::callbackEvent: audio write error."; - error( RtAudioError::WARNING ); - // Continue on to input section. - } - } - - if ( stream_.mode == INPUT || stream_.mode == DUPLEX ) { - - // Setup parameters. - if ( stream_.doConvertBuffer[1] ) { - buffer = stream_.deviceBuffer; - samples = stream_.bufferSize * stream_.nDeviceChannels[1]; - format = stream_.deviceFormat[1]; - } - else { - buffer = stream_.userBuffer[1]; - samples = stream_.bufferSize * stream_.nUserChannels[1]; - format = stream_.userFormat; - } - - // Read samples from device. - result = read( handle->id[1], buffer, samples * formatBytes(format) ); - - if ( result == -1 ) { - // We'll assume this is an overrun, though there isn't a - // specific means for determining that. - handle->xrun[1] = true; - errorText_ = "RtApiOss::callbackEvent: audio read error."; - error( RtAudioError::WARNING ); - goto unlock; - } - - // Do byte swapping if necessary. - if ( stream_.doByteSwap[1] ) - byteSwapBuffer( buffer, samples, format ); - - // Do buffer conversion if necessary. - if ( stream_.doConvertBuffer[1] ) - convertBuffer( stream_.userBuffer[1], stream_.deviceBuffer, stream_.convertInfo[1] ); - } - - unlock: - MUTEX_UNLOCK( &stream_.mutex ); - - RtApi::tickStreamTime(); - if ( doStopStream == 1 ) this->stopStream(); -} - -static void *ossCallbackHandler( void *ptr ) -{ - CallbackInfo *info = (CallbackInfo *) ptr; - RtApiOss *object = (RtApiOss *) info->object; - bool *isRunning = &info->isRunning; - - while ( *isRunning == true ) { - pthread_testcancel(); - object->callbackEvent(); - } - - pthread_exit( NULL ); -} - -//******************** End of __LINUX_OSS__ *********************// -#endif - - -// *************************************************** // -// -// Protected common (OS-independent) RtAudio methods. -// -// *************************************************** // - -// This method can be modified to control the behavior of error -// message printing. -void RtApi :: error( RtAudioError::Type type ) -{ - errorStream_.str(""); // clear the ostringstream - - RtAudioErrorCallback errorCallback = (RtAudioErrorCallback) stream_.callbackInfo.errorCallback; - if ( errorCallback ) { - // abortStream() can generate new error messages. Ignore them. Just keep original one. - - if ( firstErrorOccurred_ ) - return; - - firstErrorOccurred_ = true; - const std::string errorMessage = errorText_; - - if ( type != RtAudioError::WARNING && stream_.state != STREAM_STOPPED) { - stream_.callbackInfo.isRunning = false; // exit from the thread - abortStream(); - } - - errorCallback( type, errorMessage ); - firstErrorOccurred_ = false; - return; - } - - if ( type == RtAudioError::WARNING && showWarnings_ == true ) - std::cerr << '\n' << errorText_ << "\n\n"; - else if ( type != RtAudioError::WARNING ) - throw( RtAudioError( errorText_, type ) ); -} - -void RtApi :: verifyStream() -{ - if ( stream_.state == STREAM_CLOSED ) { - errorText_ = "RtApi:: a stream is not open!"; - error( RtAudioError::INVALID_USE ); - } -} - -void RtApi :: clearStreamInfo() -{ - stream_.mode = UNINITIALIZED; - stream_.state = STREAM_CLOSED; - stream_.sampleRate = 0; - stream_.bufferSize = 0; - stream_.nBuffers = 0; - stream_.userFormat = 0; - stream_.userInterleaved = true; - stream_.streamTime = 0.0; - stream_.apiHandle = 0; - stream_.deviceBuffer = 0; - stream_.callbackInfo.callback = 0; - stream_.callbackInfo.userData = 0; - stream_.callbackInfo.isRunning = false; - stream_.callbackInfo.errorCallback = 0; - for ( int i=0; i<2; i++ ) { - stream_.device[i] = 11111; - stream_.doConvertBuffer[i] = false; - stream_.deviceInterleaved[i] = true; - stream_.doByteSwap[i] = false; - stream_.nUserChannels[i] = 0; - stream_.nDeviceChannels[i] = 0; - stream_.channelOffset[i] = 0; - stream_.deviceFormat[i] = 0; - stream_.latency[i] = 0; - stream_.userBuffer[i] = 0; - stream_.convertInfo[i].channels = 0; - stream_.convertInfo[i].inJump = 0; - stream_.convertInfo[i].outJump = 0; - stream_.convertInfo[i].inFormat = 0; - stream_.convertInfo[i].outFormat = 0; - stream_.convertInfo[i].inOffset.clear(); - stream_.convertInfo[i].outOffset.clear(); - } -} - -unsigned int RtApi :: formatBytes( RtAudioFormat format ) -{ - if ( format == RTAUDIO_SINT16 ) - return 2; - else if ( format == RTAUDIO_SINT32 || format == RTAUDIO_FLOAT32 ) - return 4; - else if ( format == RTAUDIO_FLOAT64 ) - return 8; - else if ( format == RTAUDIO_SINT24 ) - return 3; - else if ( format == RTAUDIO_SINT8 ) - return 1; - - errorText_ = "RtApi::formatBytes: undefined format."; - error( RtAudioError::WARNING ); - - return 0; -} - -void RtApi :: setConvertInfo( StreamMode mode, unsigned int firstChannel ) -{ - if ( mode == INPUT ) { // convert device to user buffer - stream_.convertInfo[mode].inJump = stream_.nDeviceChannels[1]; - stream_.convertInfo[mode].outJump = stream_.nUserChannels[1]; - stream_.convertInfo[mode].inFormat = stream_.deviceFormat[1]; - stream_.convertInfo[mode].outFormat = stream_.userFormat; - } - else { // convert user to device buffer - stream_.convertInfo[mode].inJump = stream_.nUserChannels[0]; - stream_.convertInfo[mode].outJump = stream_.nDeviceChannels[0]; - stream_.convertInfo[mode].inFormat = stream_.userFormat; - stream_.convertInfo[mode].outFormat = stream_.deviceFormat[0]; - } - - if ( stream_.convertInfo[mode].inJump < stream_.convertInfo[mode].outJump ) - stream_.convertInfo[mode].channels = stream_.convertInfo[mode].inJump; - else - stream_.convertInfo[mode].channels = stream_.convertInfo[mode].outJump; - - // Set up the interleave/deinterleave offsets. - if ( stream_.deviceInterleaved[mode] != stream_.userInterleaved ) { - if ( ( mode == OUTPUT && stream_.deviceInterleaved[mode] ) || - ( mode == INPUT && stream_.userInterleaved ) ) { - for ( int k=0; k<stream_.convertInfo[mode].channels; k++ ) { - stream_.convertInfo[mode].inOffset.push_back( k * stream_.bufferSize ); - stream_.convertInfo[mode].outOffset.push_back( k ); - stream_.convertInfo[mode].inJump = 1; - } - } - else { - for ( int k=0; k<stream_.convertInfo[mode].channels; k++ ) { - stream_.convertInfo[mode].inOffset.push_back( k ); - stream_.convertInfo[mode].outOffset.push_back( k * stream_.bufferSize ); - stream_.convertInfo[mode].outJump = 1; - } - } - } - else { // no (de)interleaving - if ( stream_.userInterleaved ) { - for ( int k=0; k<stream_.convertInfo[mode].channels; k++ ) { - stream_.convertInfo[mode].inOffset.push_back( k ); - stream_.convertInfo[mode].outOffset.push_back( k ); - } - } - else { - for ( int k=0; k<stream_.convertInfo[mode].channels; k++ ) { - stream_.convertInfo[mode].inOffset.push_back( k * stream_.bufferSize ); - stream_.convertInfo[mode].outOffset.push_back( k * stream_.bufferSize ); - stream_.convertInfo[mode].inJump = 1; - stream_.convertInfo[mode].outJump = 1; - } - } - } - - // Add channel offset. - if ( firstChannel > 0 ) { - if ( stream_.deviceInterleaved[mode] ) { - if ( mode == OUTPUT ) { - for ( int k=0; k<stream_.convertInfo[mode].channels; k++ ) - stream_.convertInfo[mode].outOffset[k] += firstChannel; - } - else { - for ( int k=0; k<stream_.convertInfo[mode].channels; k++ ) - stream_.convertInfo[mode].inOffset[k] += firstChannel; - } - } - else { - if ( mode == OUTPUT ) { - for ( int k=0; k<stream_.convertInfo[mode].channels; k++ ) - stream_.convertInfo[mode].outOffset[k] += ( firstChannel * stream_.bufferSize ); - } - else { - for ( int k=0; k<stream_.convertInfo[mode].channels; k++ ) - stream_.convertInfo[mode].inOffset[k] += ( firstChannel * stream_.bufferSize ); - } - } - } -} - -void RtApi :: convertBuffer( char *outBuffer, char *inBuffer, ConvertInfo &info ) -{ - // This function does format conversion, input/output channel compensation, and - // data interleaving/deinterleaving. 24-bit integers are assumed to occupy - // the lower three bytes of a 32-bit integer. - - // Clear our device buffer when in/out duplex device channels are different - if ( outBuffer == stream_.deviceBuffer && stream_.mode == DUPLEX && - ( stream_.nDeviceChannels[0] < stream_.nDeviceChannels[1] ) ) - memset( outBuffer, 0, stream_.bufferSize * info.outJump * formatBytes( info.outFormat ) ); - - int j; - if (info.outFormat == RTAUDIO_FLOAT64) { - Float64 scale; - Float64 *out = (Float64 *)outBuffer; - - if (info.inFormat == RTAUDIO_SINT8) { - signed char *in = (signed char *)inBuffer; - scale = 1.0 / 127.5; - for (unsigned int i=0; i<stream_.bufferSize; i++) { - for (j=0; j<info.channels; j++) { - out[info.outOffset[j]] = (Float64) in[info.inOffset[j]]; - out[info.outOffset[j]] += 0.5; - out[info.outOffset[j]] *= scale; - } - in += info.inJump; - out += info.outJump; - } - } - else if (info.inFormat == RTAUDIO_SINT16) { - Int16 *in = (Int16 *)inBuffer; - scale = 1.0 / 32767.5; - for (unsigned int i=0; i<stream_.bufferSize; i++) { - for (j=0; j<info.channels; j++) { - out[info.outOffset[j]] = (Float64) in[info.inOffset[j]]; - out[info.outOffset[j]] += 0.5; - out[info.outOffset[j]] *= scale; - } - in += info.inJump; - out += info.outJump; - } - } - else if (info.inFormat == RTAUDIO_SINT24) { - Int24 *in = (Int24 *)inBuffer; - scale = 1.0 / 8388607.5; - for (unsigned int i=0; i<stream_.bufferSize; i++) { - for (j=0; j<info.channels; j++) { - out[info.outOffset[j]] = (Float64) (in[info.inOffset[j]].asInt()); - out[info.outOffset[j]] += 0.5; - out[info.outOffset[j]] *= scale; - } - in += info.inJump; - out += info.outJump; - } - } - else if (info.inFormat == RTAUDIO_SINT32) { - Int32 *in = (Int32 *)inBuffer; - scale = 1.0 / 2147483647.5; - for (unsigned int i=0; i<stream_.bufferSize; i++) { - for (j=0; j<info.channels; j++) { - out[info.outOffset[j]] = (Float64) in[info.inOffset[j]]; - out[info.outOffset[j]] += 0.5; - out[info.outOffset[j]] *= scale; - } - in += info.inJump; - out += info.outJump; - } - } - else if (info.inFormat == RTAUDIO_FLOAT32) { - Float32 *in = (Float32 *)inBuffer; - for (unsigned int i=0; i<stream_.bufferSize; i++) { - for (j=0; j<info.channels; j++) { - out[info.outOffset[j]] = (Float64) in[info.inOffset[j]]; - } - in += info.inJump; - out += info.outJump; - } - } - else if (info.inFormat == RTAUDIO_FLOAT64) { - // Channel compensation and/or (de)interleaving only. - Float64 *in = (Float64 *)inBuffer; - for (unsigned int i=0; i<stream_.bufferSize; i++) { - for (j=0; j<info.channels; j++) { - out[info.outOffset[j]] = in[info.inOffset[j]]; - } - in += info.inJump; - out += info.outJump; - } - } - } - else if (info.outFormat == RTAUDIO_FLOAT32) { - Float32 scale; - Float32 *out = (Float32 *)outBuffer; - - if (info.inFormat == RTAUDIO_SINT8) { - signed char *in = (signed char *)inBuffer; - scale = (Float32) ( 1.0 / 127.5 ); - for (unsigned int i=0; i<stream_.bufferSize; i++) { - for (j=0; j<info.channels; j++) { - out[info.outOffset[j]] = (Float32) in[info.inOffset[j]]; - out[info.outOffset[j]] += 0.5; - out[info.outOffset[j]] *= scale; - } - in += info.inJump; - out += info.outJump; - } - } - else if (info.inFormat == RTAUDIO_SINT16) { - Int16 *in = (Int16 *)inBuffer; - scale = (Float32) ( 1.0 / 32767.5 ); - for (unsigned int i=0; i<stream_.bufferSize; i++) { - for (j=0; j<info.channels; j++) { - out[info.outOffset[j]] = (Float32) in[info.inOffset[j]]; - out[info.outOffset[j]] += 0.5; - out[info.outOffset[j]] *= scale; - } - in += info.inJump; - out += info.outJump; - } - } - else if (info.inFormat == RTAUDIO_SINT24) { - Int24 *in = (Int24 *)inBuffer; - scale = (Float32) ( 1.0 / 8388607.5 ); - for (unsigned int i=0; i<stream_.bufferSize; i++) { - for (j=0; j<info.channels; j++) { - out[info.outOffset[j]] = (Float32) (in[info.inOffset[j]].asInt()); - out[info.outOffset[j]] += 0.5; - out[info.outOffset[j]] *= scale; - } - in += info.inJump; - out += info.outJump; - } - } - else if (info.inFormat == RTAUDIO_SINT32) { - Int32 *in = (Int32 *)inBuffer; - scale = (Float32) ( 1.0 / 2147483647.5 ); - for (unsigned int i=0; i<stream_.bufferSize; i++) { - for (j=0; j<info.channels; j++) { - out[info.outOffset[j]] = (Float32) in[info.inOffset[j]]; - out[info.outOffset[j]] += 0.5; - out[info.outOffset[j]] *= scale; - } - in += info.inJump; - out += info.outJump; - } - } - else if (info.inFormat == RTAUDIO_FLOAT32) { - // Channel compensation and/or (de)interleaving only. - Float32 *in = (Float32 *)inBuffer; - for (unsigned int i=0; i<stream_.bufferSize; i++) { - for (j=0; j<info.channels; j++) { - out[info.outOffset[j]] = in[info.inOffset[j]]; - } - in += info.inJump; - out += info.outJump; - } - } - else if (info.inFormat == RTAUDIO_FLOAT64) { - Float64 *in = (Float64 *)inBuffer; - for (unsigned int i=0; i<stream_.bufferSize; i++) { - for (j=0; j<info.channels; j++) { - out[info.outOffset[j]] = (Float32) in[info.inOffset[j]]; - } - in += info.inJump; - out += info.outJump; - } - } - } - else if (info.outFormat == RTAUDIO_SINT32) { - Int32 *out = (Int32 *)outBuffer; - if (info.inFormat == RTAUDIO_SINT8) { - signed char *in = (signed char *)inBuffer; - for (unsigned int i=0; i<stream_.bufferSize; i++) { - for (j=0; j<info.channels; j++) { - out[info.outOffset[j]] = (Int32) in[info.inOffset[j]]; - out[info.outOffset[j]] <<= 24; - } - in += info.inJump; - out += info.outJump; - } - } - else if (info.inFormat == RTAUDIO_SINT16) { - Int16 *in = (Int16 *)inBuffer; - for (unsigned int i=0; i<stream_.bufferSize; i++) { - for (j=0; j<info.channels; j++) { - out[info.outOffset[j]] = (Int32) in[info.inOffset[j]]; - out[info.outOffset[j]] <<= 16; - } - in += info.inJump; - out += info.outJump; - } - } - else if (info.inFormat == RTAUDIO_SINT24) { - Int24 *in = (Int24 *)inBuffer; - for (unsigned int i=0; i<stream_.bufferSize; i++) { - for (j=0; j<info.channels; j++) { - out[info.outOffset[j]] = (Int32) in[info.inOffset[j]].asInt(); - out[info.outOffset[j]] <<= 8; - } - in += info.inJump; - out += info.outJump; - } - } - else if (info.inFormat == RTAUDIO_SINT32) { - // Channel compensation and/or (de)interleaving only. - Int32 *in = (Int32 *)inBuffer; - for (unsigned int i=0; i<stream_.bufferSize; i++) { - for (j=0; j<info.channels; j++) { - out[info.outOffset[j]] = in[info.inOffset[j]]; - } - in += info.inJump; - out += info.outJump; - } - } - else if (info.inFormat == RTAUDIO_FLOAT32) { - Float32 *in = (Float32 *)inBuffer; - for (unsigned int i=0; i<stream_.bufferSize; i++) { - for (j=0; j<info.channels; j++) { - out[info.outOffset[j]] = (Int32) (in[info.inOffset[j]] * 2147483647.5 - 0.5); - } - in += info.inJump; - out += info.outJump; - } - } - else if (info.inFormat == RTAUDIO_FLOAT64) { - Float64 *in = (Float64 *)inBuffer; - for (unsigned int i=0; i<stream_.bufferSize; i++) { - for (j=0; j<info.channels; j++) { - out[info.outOffset[j]] = (Int32) (in[info.inOffset[j]] * 2147483647.5 - 0.5); - } - in += info.inJump; - out += info.outJump; - } - } - } - else if (info.outFormat == RTAUDIO_SINT24) { - Int24 *out = (Int24 *)outBuffer; - if (info.inFormat == RTAUDIO_SINT8) { - signed char *in = (signed char *)inBuffer; - for (unsigned int i=0; i<stream_.bufferSize; i++) { - for (j=0; j<info.channels; j++) { - out[info.outOffset[j]] = (Int32) (in[info.inOffset[j]] << 16); - //out[info.outOffset[j]] <<= 16; - } - in += info.inJump; - out += info.outJump; - } - } - else if (info.inFormat == RTAUDIO_SINT16) { - Int16 *in = (Int16 *)inBuffer; - for (unsigned int i=0; i<stream_.bufferSize; i++) { - for (j=0; j<info.channels; j++) { - out[info.outOffset[j]] = (Int32) (in[info.inOffset[j]] << 8); - //out[info.outOffset[j]] <<= 8; - } - in += info.inJump; - out += info.outJump; - } - } - else if (info.inFormat == RTAUDIO_SINT24) { - // Channel compensation and/or (de)interleaving only. - Int24 *in = (Int24 *)inBuffer; - for (unsigned int i=0; i<stream_.bufferSize; i++) { - for (j=0; j<info.channels; j++) { - out[info.outOffset[j]] = in[info.inOffset[j]]; - } - in += info.inJump; - out += info.outJump; - } - } - else if (info.inFormat == RTAUDIO_SINT32) { - Int32 *in = (Int32 *)inBuffer; - for (unsigned int i=0; i<stream_.bufferSize; i++) { - for (j=0; j<info.channels; j++) { - out[info.outOffset[j]] = (Int32) (in[info.inOffset[j]] >> 8); - //out[info.outOffset[j]] >>= 8; - } - in += info.inJump; - out += info.outJump; - } - } - else if (info.inFormat == RTAUDIO_FLOAT32) { - Float32 *in = (Float32 *)inBuffer; - for (unsigned int i=0; i<stream_.bufferSize; i++) { - for (j=0; j<info.channels; j++) { - out[info.outOffset[j]] = (Int32) (in[info.inOffset[j]] * 8388607.5 - 0.5); - } - in += info.inJump; - out += info.outJump; - } - } - else if (info.inFormat == RTAUDIO_FLOAT64) { - Float64 *in = (Float64 *)inBuffer; - for (unsigned int i=0; i<stream_.bufferSize; i++) { - for (j=0; j<info.channels; j++) { - out[info.outOffset[j]] = (Int32) (in[info.inOffset[j]] * 8388607.5 - 0.5); - } - in += info.inJump; - out += info.outJump; - } - } - } - else if (info.outFormat == RTAUDIO_SINT16) { - Int16 *out = (Int16 *)outBuffer; - if (info.inFormat == RTAUDIO_SINT8) { - signed char *in = (signed char *)inBuffer; - for (unsigned int i=0; i<stream_.bufferSize; i++) { - for (j=0; j<info.channels; j++) { - out[info.outOffset[j]] = (Int16) in[info.inOffset[j]]; - out[info.outOffset[j]] <<= 8; - } - in += info.inJump; - out += info.outJump; - } - } - else if (info.inFormat == RTAUDIO_SINT16) { - // Channel compensation and/or (de)interleaving only. - Int16 *in = (Int16 *)inBuffer; - for (unsigned int i=0; i<stream_.bufferSize; i++) { - for (j=0; j<info.channels; j++) { - out[info.outOffset[j]] = in[info.inOffset[j]]; - } - in += info.inJump; - out += info.outJump; - } - } - else if (info.inFormat == RTAUDIO_SINT24) { - Int24 *in = (Int24 *)inBuffer; - for (unsigned int i=0; i<stream_.bufferSize; i++) { - for (j=0; j<info.channels; j++) { - out[info.outOffset[j]] = (Int16) (in[info.inOffset[j]].asInt() >> 8); - } - in += info.inJump; - out += info.outJump; - } - } - else if (info.inFormat == RTAUDIO_SINT32) { - Int32 *in = (Int32 *)inBuffer; - for (unsigned int i=0; i<stream_.bufferSize; i++) { - for (j=0; j<info.channels; j++) { - out[info.outOffset[j]] = (Int16) ((in[info.inOffset[j]] >> 16) & 0x0000ffff); - } - in += info.inJump; - out += info.outJump; - } - } - else if (info.inFormat == RTAUDIO_FLOAT32) { - Float32 *in = (Float32 *)inBuffer; - for (unsigned int i=0; i<stream_.bufferSize; i++) { - for (j=0; j<info.channels; j++) { - out[info.outOffset[j]] = (Int16) (in[info.inOffset[j]] * 32767.5 - 0.5); - } - in += info.inJump; - out += info.outJump; - } - } - else if (info.inFormat == RTAUDIO_FLOAT64) { - Float64 *in = (Float64 *)inBuffer; - for (unsigned int i=0; i<stream_.bufferSize; i++) { - for (j=0; j<info.channels; j++) { - out[info.outOffset[j]] = (Int16) (in[info.inOffset[j]] * 32767.5 - 0.5); - } - in += info.inJump; - out += info.outJump; - } - } - } - else if (info.outFormat == RTAUDIO_SINT8) { - signed char *out = (signed char *)outBuffer; - if (info.inFormat == RTAUDIO_SINT8) { - // Channel compensation and/or (de)interleaving only. - signed char *in = (signed char *)inBuffer; - for (unsigned int i=0; i<stream_.bufferSize; i++) { - for (j=0; j<info.channels; j++) { - out[info.outOffset[j]] = in[info.inOffset[j]]; - } - in += info.inJump; - out += info.outJump; - } - } - if (info.inFormat == RTAUDIO_SINT16) { - Int16 *in = (Int16 *)inBuffer; - for (unsigned int i=0; i<stream_.bufferSize; i++) { - for (j=0; j<info.channels; j++) { - out[info.outOffset[j]] = (signed char) ((in[info.inOffset[j]] >> 8) & 0x00ff); - } - in += info.inJump; - out += info.outJump; - } - } - else if (info.inFormat == RTAUDIO_SINT24) { - Int24 *in = (Int24 *)inBuffer; - for (unsigned int i=0; i<stream_.bufferSize; i++) { - for (j=0; j<info.channels; j++) { - out[info.outOffset[j]] = (signed char) (in[info.inOffset[j]].asInt() >> 16); - } - in += info.inJump; - out += info.outJump; - } - } - else if (info.inFormat == RTAUDIO_SINT32) { - Int32 *in = (Int32 *)inBuffer; - for (unsigned int i=0; i<stream_.bufferSize; i++) { - for (j=0; j<info.channels; j++) { - out[info.outOffset[j]] = (signed char) ((in[info.inOffset[j]] >> 24) & 0x000000ff); - } - in += info.inJump; - out += info.outJump; - } - } - else if (info.inFormat == RTAUDIO_FLOAT32) { - Float32 *in = (Float32 *)inBuffer; - for (unsigned int i=0; i<stream_.bufferSize; i++) { - for (j=0; j<info.channels; j++) { - out[info.outOffset[j]] = (signed char) (in[info.inOffset[j]] * 127.5 - 0.5); - } - in += info.inJump; - out += info.outJump; - } - } - else if (info.inFormat == RTAUDIO_FLOAT64) { - Float64 *in = (Float64 *)inBuffer; - for (unsigned int i=0; i<stream_.bufferSize; i++) { - for (j=0; j<info.channels; j++) { - out[info.outOffset[j]] = (signed char) (in[info.inOffset[j]] * 127.5 - 0.5); - } - in += info.inJump; - out += info.outJump; - } - } - } -} - -//static inline uint16_t bswap_16(uint16_t x) { return (x>>8) | (x<<8); } -//static inline uint32_t bswap_32(uint32_t x) { return (bswap_16(x&0xffff)<<16) | (bswap_16(x>>16)); } -//static inline uint64_t bswap_64(uint64_t x) { return (((unsigned long long)bswap_32(x&0xffffffffull))<<32) | (bswap_32(x>>32)); } - -void RtApi :: byteSwapBuffer( char *buffer, unsigned int samples, RtAudioFormat format ) -{ - char val; - char *ptr; - - ptr = buffer; - if ( format == RTAUDIO_SINT16 ) { - for ( unsigned int i=0; i<samples; i++ ) { - // Swap 1st and 2nd bytes. - val = *(ptr); - *(ptr) = *(ptr+1); - *(ptr+1) = val; - - // Increment 2 bytes. - ptr += 2; - } - } - else if ( format == RTAUDIO_SINT32 || - format == RTAUDIO_FLOAT32 ) { - for ( unsigned int i=0; i<samples; i++ ) { - // Swap 1st and 4th bytes. - val = *(ptr); - *(ptr) = *(ptr+3); - *(ptr+3) = val; - - // Swap 2nd and 3rd bytes. - ptr += 1; - val = *(ptr); - *(ptr) = *(ptr+1); - *(ptr+1) = val; - - // Increment 3 more bytes. - ptr += 3; - } - } - else if ( format == RTAUDIO_SINT24 ) { - for ( unsigned int i=0; i<samples; i++ ) { - // Swap 1st and 3rd bytes. - val = *(ptr); - *(ptr) = *(ptr+2); - *(ptr+2) = val; - - // Increment 2 more bytes. - ptr += 2; - } - } - else if ( format == RTAUDIO_FLOAT64 ) { - for ( unsigned int i=0; i<samples; i++ ) { - // Swap 1st and 8th bytes - val = *(ptr); - *(ptr) = *(ptr+7); - *(ptr+7) = val; - - // Swap 2nd and 7th bytes - ptr += 1; - val = *(ptr); - *(ptr) = *(ptr+5); - *(ptr+5) = val; - - // Swap 3rd and 6th bytes - ptr += 1; - val = *(ptr); - *(ptr) = *(ptr+3); - *(ptr+3) = val; - - // Swap 4th and 5th bytes - ptr += 1; - val = *(ptr); - *(ptr) = *(ptr+1); - *(ptr+1) = val; - - // Increment 5 more bytes. - ptr += 5; - } - } -} - - // Indentation settings for Vim and Emacs - // - // Local Variables: - // c-basic-offset: 2 - // indent-tabs-mode: nil - // End: - // - // vim: et sts=2 sw=2 - -#endif // RTAUDIO_ENABLED -GODOT- diff --git a/thirdparty/rtaudio/RtAudio.h b/thirdparty/rtaudio/RtAudio.h deleted file mode 100644 index aab109d907..0000000000 --- a/thirdparty/rtaudio/RtAudio.h +++ /dev/null @@ -1,1183 +0,0 @@ -// -GODOT- Start - -#ifdef RTAUDIO_ENABLED - -#if defined(OSX_ENABLED) - #define __MACOSX_CORE__ -#elif defined(UNIX_ENABLED) - #define __LINUX_ALSA__ -#elif defined(WINDOWS_ENABLED) - #if defined(UWP_ENABLED) - #define __RTAUDIO_DUMMY__ - #else - #define __WINDOWS_DS__ - #endif -#endif - -// -GODOT- End - -/************************************************************************/ -/*! \class RtAudio - \brief Realtime audio i/o C++ classes. - - RtAudio provides a common API (Application Programming Interface) - for realtime audio input/output across Linux (native ALSA, Jack, - and OSS), Macintosh OS X (CoreAudio and Jack), and Windows - (DirectSound, ASIO and WASAPI) operating systems. - - RtAudio WWW site: http://www.music.mcgill.ca/~gary/rtaudio/ - - RtAudio: realtime audio i/o C++ classes - Copyright (c) 2001-2016 Gary P. Scavone - - Permission is hereby granted, free of charge, to any person - obtaining a copy of this software and associated documentation files - (the "Software"), to deal in the Software without restriction, - including without limitation the rights to use, copy, modify, merge, - publish, distribute, sublicense, and/or sell copies of the Software, - and to permit persons to whom the Software is furnished to do so, - subject to the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - Any person wishing to distribute modifications to the Software is - asked to send the modifications to the original developer so that - they can be incorporated into the canonical version. This is, - however, not a binding provision of this license. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR - ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF - CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ -/************************************************************************/ - -/*! - \file RtAudio.h - */ - -#ifndef __RTAUDIO_H -#define __RTAUDIO_H - -#define RTAUDIO_VERSION "4.1.2" - -#include <string> -#include <vector> -#include <exception> -#include <iostream> - -/*! \typedef typedef unsigned long RtAudioFormat; - \brief RtAudio data format type. - - Support for signed integers and floats. Audio data fed to/from an - RtAudio stream is assumed to ALWAYS be in host byte order. The - internal routines will automatically take care of any necessary - byte-swapping between the host format and the soundcard. Thus, - endian-ness is not a concern in the following format definitions. - - - \e RTAUDIO_SINT8: 8-bit signed integer. - - \e RTAUDIO_SINT16: 16-bit signed integer. - - \e RTAUDIO_SINT24: 24-bit signed integer. - - \e RTAUDIO_SINT32: 32-bit signed integer. - - \e RTAUDIO_FLOAT32: Normalized between plus/minus 1.0. - - \e RTAUDIO_FLOAT64: Normalized between plus/minus 1.0. -*/ -typedef unsigned long RtAudioFormat; -static const RtAudioFormat RTAUDIO_SINT8 = 0x1; // 8-bit signed integer. -static const RtAudioFormat RTAUDIO_SINT16 = 0x2; // 16-bit signed integer. -static const RtAudioFormat RTAUDIO_SINT24 = 0x4; // 24-bit signed integer. -static const RtAudioFormat RTAUDIO_SINT32 = 0x8; // 32-bit signed integer. -static const RtAudioFormat RTAUDIO_FLOAT32 = 0x10; // Normalized between plus/minus 1.0. -static const RtAudioFormat RTAUDIO_FLOAT64 = 0x20; // Normalized between plus/minus 1.0. - -/*! \typedef typedef unsigned long RtAudioStreamFlags; - \brief RtAudio stream option flags. - - The following flags can be OR'ed together to allow a client to - make changes to the default stream behavior: - - - \e RTAUDIO_NONINTERLEAVED: Use non-interleaved buffers (default = interleaved). - - \e RTAUDIO_MINIMIZE_LATENCY: Attempt to set stream parameters for lowest possible latency. - - \e RTAUDIO_HOG_DEVICE: Attempt grab device for exclusive use. - - \e RTAUDIO_ALSA_USE_DEFAULT: Use the "default" PCM device (ALSA only). - - By default, RtAudio streams pass and receive audio data from the - client in an interleaved format. By passing the - RTAUDIO_NONINTERLEAVED flag to the openStream() function, audio - data will instead be presented in non-interleaved buffers. In - this case, each buffer argument in the RtAudioCallback function - will point to a single array of data, with \c nFrames samples for - each channel concatenated back-to-back. For example, the first - sample of data for the second channel would be located at index \c - nFrames (assuming the \c buffer pointer was recast to the correct - data type for the stream). - - Certain audio APIs offer a number of parameters that influence the - I/O latency of a stream. By default, RtAudio will attempt to set - these parameters internally for robust (glitch-free) performance - (though some APIs, like Windows Direct Sound, make this difficult). - By passing the RTAUDIO_MINIMIZE_LATENCY flag to the openStream() - function, internal stream settings will be influenced in an attempt - to minimize stream latency, though possibly at the expense of stream - performance. - - If the RTAUDIO_HOG_DEVICE flag is set, RtAudio will attempt to - open the input and/or output stream device(s) for exclusive use. - Note that this is not possible with all supported audio APIs. - - If the RTAUDIO_SCHEDULE_REALTIME flag is set, RtAudio will attempt - to select realtime scheduling (round-robin) for the callback thread. - - If the RTAUDIO_ALSA_USE_DEFAULT flag is set, RtAudio will attempt to - open the "default" PCM device when using the ALSA API. Note that this - will override any specified input or output device id. -*/ -typedef unsigned int RtAudioStreamFlags; -static const RtAudioStreamFlags RTAUDIO_NONINTERLEAVED = 0x1; // Use non-interleaved buffers (default = interleaved). -static const RtAudioStreamFlags RTAUDIO_MINIMIZE_LATENCY = 0x2; // Attempt to set stream parameters for lowest possible latency. -static const RtAudioStreamFlags RTAUDIO_HOG_DEVICE = 0x4; // Attempt grab device and prevent use by others. -static const RtAudioStreamFlags RTAUDIO_SCHEDULE_REALTIME = 0x8; // Try to select realtime scheduling for callback thread. -static const RtAudioStreamFlags RTAUDIO_ALSA_USE_DEFAULT = 0x10; // Use the "default" PCM device (ALSA only). - -/*! \typedef typedef unsigned long RtAudioStreamStatus; - \brief RtAudio stream status (over- or underflow) flags. - - Notification of a stream over- or underflow is indicated by a - non-zero stream \c status argument in the RtAudioCallback function. - The stream status can be one of the following two options, - depending on whether the stream is open for output and/or input: - - - \e RTAUDIO_INPUT_OVERFLOW: Input data was discarded because of an overflow condition at the driver. - - \e RTAUDIO_OUTPUT_UNDERFLOW: The output buffer ran low, likely producing a break in the output sound. -*/ -typedef unsigned int RtAudioStreamStatus; -static const RtAudioStreamStatus RTAUDIO_INPUT_OVERFLOW = 0x1; // Input data was discarded because of an overflow condition at the driver. -static const RtAudioStreamStatus RTAUDIO_OUTPUT_UNDERFLOW = 0x2; // The output buffer ran low, likely causing a gap in the output sound. - -//! RtAudio callback function prototype. -/*! - All RtAudio clients must create a function of type RtAudioCallback - to read and/or write data from/to the audio stream. When the - underlying audio system is ready for new input or output data, this - function will be invoked. - - \param outputBuffer For output (or duplex) streams, the client - should write \c nFrames of audio sample frames into this - buffer. This argument should be recast to the datatype - specified when the stream was opened. For input-only - streams, this argument will be NULL. - - \param inputBuffer For input (or duplex) streams, this buffer will - hold \c nFrames of input audio sample frames. This - argument should be recast to the datatype specified when the - stream was opened. For output-only streams, this argument - will be NULL. - - \param nFrames The number of sample frames of input or output - data in the buffers. The actual buffer size in bytes is - dependent on the data type and number of channels in use. - - \param streamTime The number of seconds that have elapsed since the - stream was started. - - \param status If non-zero, this argument indicates a data overflow - or underflow condition for the stream. The particular - condition can be determined by comparison with the - RtAudioStreamStatus flags. - - \param userData A pointer to optional data provided by the client - when opening the stream (default = NULL). - - To continue normal stream operation, the RtAudioCallback function - should return a value of zero. To stop the stream and drain the - output buffer, the function should return a value of one. To abort - the stream immediately, the client should return a value of two. - */ -typedef int (*RtAudioCallback)( void *outputBuffer, void *inputBuffer, - unsigned int nFrames, - double streamTime, - RtAudioStreamStatus status, - void *userData ); - -/************************************************************************/ -/*! \class RtAudioError - \brief Exception handling class for RtAudio. - - The RtAudioError class is quite simple but it does allow errors to be - "caught" by RtAudioError::Type. See the RtAudio documentation to know - which methods can throw an RtAudioError. -*/ -/************************************************************************/ - -class RtAudioError : public std::exception -{ - public: - //! Defined RtAudioError types. - enum Type { - WARNING, /*!< A non-critical error. */ - DEBUG_WARNING, /*!< A non-critical error which might be useful for debugging. */ - UNSPECIFIED, /*!< The default, unspecified error type. */ - NO_DEVICES_FOUND, /*!< No devices found on system. */ - INVALID_DEVICE, /*!< An invalid device ID was specified. */ - MEMORY_ERROR, /*!< An error occured during memory allocation. */ - INVALID_PARAMETER, /*!< An invalid parameter was specified to a function. */ - INVALID_USE, /*!< The function was called incorrectly. */ - DRIVER_ERROR, /*!< A system driver error occured. */ - SYSTEM_ERROR, /*!< A system error occured. */ - THREAD_ERROR /*!< A thread error occured. */ - }; - - //! The constructor. - RtAudioError( const std::string& message, Type type = RtAudioError::UNSPECIFIED ) throw() : message_(message), type_(type) {} - - //! The destructor. - virtual ~RtAudioError( void ) throw() {} - - //! Prints thrown error message to stderr. - virtual void printMessage( void ) const throw() { std::cerr << '\n' << message_ << "\n\n"; } - - //! Returns the thrown error message type. - virtual const Type& getType(void) const throw() { return type_; } - - //! Returns the thrown error message string. - virtual const std::string& getMessage(void) const throw() { return message_; } - - //! Returns the thrown error message as a c-style string. - virtual const char* what( void ) const throw() { return message_.c_str(); } - - protected: - std::string message_; - Type type_; -}; - -//! RtAudio error callback function prototype. -/*! - \param type Type of error. - \param errorText Error description. - */ -typedef void (*RtAudioErrorCallback)( RtAudioError::Type type, const std::string &errorText ); - -// **************************************************************** // -// -// RtAudio class declaration. -// -// RtAudio is a "controller" used to select an available audio i/o -// interface. It presents a common API for the user to call but all -// functionality is implemented by the class RtApi and its -// subclasses. RtAudio creates an instance of an RtApi subclass -// based on the user's API choice. If no choice is made, RtAudio -// attempts to make a "logical" API selection. -// -// **************************************************************** // - -class RtApi; - -class RtAudio -{ - public: - - //! Audio API specifier arguments. - enum Api { - UNSPECIFIED, /*!< Search for a working compiled API. */ - LINUX_ALSA, /*!< The Advanced Linux Sound Architecture API. */ - LINUX_PULSE, /*!< The Linux PulseAudio API. */ - LINUX_OSS, /*!< The Linux Open Sound System API. */ - UNIX_JACK, /*!< The Jack Low-Latency Audio Server API. */ - MACOSX_CORE, /*!< Macintosh OS-X Core Audio API. */ - WINDOWS_WASAPI, /*!< The Microsoft WASAPI API. */ - WINDOWS_ASIO, /*!< The Steinberg Audio Stream I/O API. */ - WINDOWS_DS, /*!< The Microsoft Direct Sound API. */ - RTAUDIO_DUMMY /*!< A compilable but non-functional API. */ - }; - - //! The public device information structure for returning queried values. - struct DeviceInfo { - bool probed; /*!< true if the device capabilities were successfully probed. */ - std::string name; /*!< Character string device identifier. */ - unsigned int outputChannels; /*!< Maximum output channels supported by device. */ - unsigned int inputChannels; /*!< Maximum input channels supported by device. */ - unsigned int duplexChannels; /*!< Maximum simultaneous input/output channels supported by device. */ - bool isDefaultOutput; /*!< true if this is the default output device. */ - bool isDefaultInput; /*!< true if this is the default input device. */ - std::vector<unsigned int> sampleRates; /*!< Supported sample rates (queried from list of standard rates). */ - unsigned int preferredSampleRate; /*!< Preferred sample rate, eg. for WASAPI the system sample rate. */ - RtAudioFormat nativeFormats; /*!< Bit mask of supported data formats. */ - - // Default constructor. - DeviceInfo() - :probed(false), outputChannels(0), inputChannels(0), duplexChannels(0), - isDefaultOutput(false), isDefaultInput(false), preferredSampleRate(0), nativeFormats(0) {} - }; - - //! The structure for specifying input or ouput stream parameters. - struct StreamParameters { - unsigned int deviceId; /*!< Device index (0 to getDeviceCount() - 1). */ - unsigned int nChannels; /*!< Number of channels. */ - unsigned int firstChannel; /*!< First channel index on device (default = 0). */ - - // Default constructor. - StreamParameters() - : deviceId(0), nChannels(0), firstChannel(0) {} - }; - - //! The structure for specifying stream options. - /*! - The following flags can be OR'ed together to allow a client to - make changes to the default stream behavior: - - - \e RTAUDIO_NONINTERLEAVED: Use non-interleaved buffers (default = interleaved). - - \e RTAUDIO_MINIMIZE_LATENCY: Attempt to set stream parameters for lowest possible latency. - - \e RTAUDIO_HOG_DEVICE: Attempt grab device for exclusive use. - - \e RTAUDIO_SCHEDULE_REALTIME: Attempt to select realtime scheduling for callback thread. - - \e RTAUDIO_ALSA_USE_DEFAULT: Use the "default" PCM device (ALSA only). - - By default, RtAudio streams pass and receive audio data from the - client in an interleaved format. By passing the - RTAUDIO_NONINTERLEAVED flag to the openStream() function, audio - data will instead be presented in non-interleaved buffers. In - this case, each buffer argument in the RtAudioCallback function - will point to a single array of data, with \c nFrames samples for - each channel concatenated back-to-back. For example, the first - sample of data for the second channel would be located at index \c - nFrames (assuming the \c buffer pointer was recast to the correct - data type for the stream). - - Certain audio APIs offer a number of parameters that influence the - I/O latency of a stream. By default, RtAudio will attempt to set - these parameters internally for robust (glitch-free) performance - (though some APIs, like Windows Direct Sound, make this difficult). - By passing the RTAUDIO_MINIMIZE_LATENCY flag to the openStream() - function, internal stream settings will be influenced in an attempt - to minimize stream latency, though possibly at the expense of stream - performance. - - If the RTAUDIO_HOG_DEVICE flag is set, RtAudio will attempt to - open the input and/or output stream device(s) for exclusive use. - Note that this is not possible with all supported audio APIs. - - If the RTAUDIO_SCHEDULE_REALTIME flag is set, RtAudio will attempt - to select realtime scheduling (round-robin) for the callback thread. - The \c priority parameter will only be used if the RTAUDIO_SCHEDULE_REALTIME - flag is set. It defines the thread's realtime priority. - - If the RTAUDIO_ALSA_USE_DEFAULT flag is set, RtAudio will attempt to - open the "default" PCM device when using the ALSA API. Note that this - will override any specified input or output device id. - - The \c numberOfBuffers parameter can be used to control stream - latency in the Windows DirectSound, Linux OSS, and Linux Alsa APIs - only. A value of two is usually the smallest allowed. Larger - numbers can potentially result in more robust stream performance, - though likely at the cost of stream latency. The value set by the - user is replaced during execution of the RtAudio::openStream() - function by the value actually used by the system. - - The \c streamName parameter can be used to set the client name - when using the Jack API. By default, the client name is set to - RtApiJack. However, if you wish to create multiple instances of - RtAudio with Jack, each instance must have a unique client name. - */ - struct StreamOptions { - RtAudioStreamFlags flags; /*!< A bit-mask of stream flags (RTAUDIO_NONINTERLEAVED, RTAUDIO_MINIMIZE_LATENCY, RTAUDIO_HOG_DEVICE, RTAUDIO_ALSA_USE_DEFAULT). */ - unsigned int numberOfBuffers; /*!< Number of stream buffers. */ - std::string streamName; /*!< A stream name (currently used only in Jack). */ - int priority; /*!< Scheduling priority of callback thread (only used with flag RTAUDIO_SCHEDULE_REALTIME). */ - - // Default constructor. - StreamOptions() - : flags(0), numberOfBuffers(0), priority(0) {} - }; - - //! A static function to determine the current RtAudio version. - static std::string getVersion( void ) throw(); - - //! A static function to determine the available compiled audio APIs. - /*! - The values returned in the std::vector can be compared against - the enumerated list values. Note that there can be more than one - API compiled for certain operating systems. - */ - static void getCompiledApi( std::vector<RtAudio::Api> &apis ) throw(); - - //! The class constructor. - /*! - The constructor performs minor initialization tasks. An exception - can be thrown if no API support is compiled. - - If no API argument is specified and multiple API support has been - compiled, the default order of use is JACK, ALSA, OSS (Linux - systems) and ASIO, DS (Windows systems). - */ - RtAudio( RtAudio::Api api=UNSPECIFIED ); - - //! The destructor. - /*! - If a stream is running or open, it will be stopped and closed - automatically. - */ - ~RtAudio() throw(); - - //! Returns the audio API specifier for the current instance of RtAudio. - RtAudio::Api getCurrentApi( void ) throw(); - - //! A public function that queries for the number of audio devices available. - /*! - This function performs a system query of available devices each time it - is called, thus supporting devices connected \e after instantiation. If - a system error occurs during processing, a warning will be issued. - */ - unsigned int getDeviceCount( void ) throw(); - - //! Return an RtAudio::DeviceInfo structure for a specified device number. - /*! - - Any device integer between 0 and getDeviceCount() - 1 is valid. - If an invalid argument is provided, an RtAudioError (type = INVALID_USE) - will be thrown. If a device is busy or otherwise unavailable, the - structure member "probed" will have a value of "false" and all - other members are undefined. If the specified device is the - current default input or output device, the corresponding - "isDefault" member will have a value of "true". - */ - RtAudio::DeviceInfo getDeviceInfo( unsigned int device ); - - //! A function that returns the index of the default output device. - /*! - If the underlying audio API does not provide a "default - device", or if no devices are available, the return value will be - 0. Note that this is a valid device identifier and it is the - client's responsibility to verify that a device is available - before attempting to open a stream. - */ - unsigned int getDefaultOutputDevice( void ) throw(); - - //! A function that returns the index of the default input device. - /*! - If the underlying audio API does not provide a "default - device", or if no devices are available, the return value will be - 0. Note that this is a valid device identifier and it is the - client's responsibility to verify that a device is available - before attempting to open a stream. - */ - unsigned int getDefaultInputDevice( void ) throw(); - - //! A public function for opening a stream with the specified parameters. - /*! - An RtAudioError (type = SYSTEM_ERROR) is thrown if a stream cannot be - opened with the specified parameters or an error occurs during - processing. An RtAudioError (type = INVALID_USE) is thrown if any - invalid device ID or channel number parameters are specified. - - \param outputParameters Specifies output stream parameters to use - when opening a stream, including a device ID, number of channels, - and starting channel number. For input-only streams, this - argument should be NULL. The device ID is an index value between - 0 and getDeviceCount() - 1. - \param inputParameters Specifies input stream parameters to use - when opening a stream, including a device ID, number of channels, - and starting channel number. For output-only streams, this - argument should be NULL. The device ID is an index value between - 0 and getDeviceCount() - 1. - \param format An RtAudioFormat specifying the desired sample data format. - \param sampleRate The desired sample rate (sample frames per second). - \param *bufferFrames A pointer to a value indicating the desired - internal buffer size in sample frames. The actual value - used by the device is returned via the same pointer. A - value of zero can be specified, in which case the lowest - allowable value is determined. - \param callback A client-defined function that will be invoked - when input data is available and/or output data is needed. - \param userData An optional pointer to data that can be accessed - from within the callback function. - \param options An optional pointer to a structure containing various - global stream options, including a list of OR'ed RtAudioStreamFlags - and a suggested number of stream buffers that can be used to - control stream latency. More buffers typically result in more - robust performance, though at a cost of greater latency. If a - value of zero is specified, a system-specific median value is - chosen. If the RTAUDIO_MINIMIZE_LATENCY flag bit is set, the - lowest allowable value is used. The actual value used is - returned via the structure argument. The parameter is API dependent. - \param errorCallback A client-defined function that will be invoked - when an error has occured. - */ - void openStream( RtAudio::StreamParameters *outputParameters, - RtAudio::StreamParameters *inputParameters, - RtAudioFormat format, unsigned int sampleRate, - unsigned int *bufferFrames, RtAudioCallback callback, - void *userData = NULL, RtAudio::StreamOptions *options = NULL, RtAudioErrorCallback errorCallback = NULL ); - - //! A function that closes a stream and frees any associated stream memory. - /*! - If a stream is not open, this function issues a warning and - returns (no exception is thrown). - */ - void closeStream( void ) throw(); - - //! A function that starts a stream. - /*! - An RtAudioError (type = SYSTEM_ERROR) is thrown if an error occurs - during processing. An RtAudioError (type = INVALID_USE) is thrown if a - stream is not open. A warning is issued if the stream is already - running. - */ - void startStream( void ); - - //! Stop a stream, allowing any samples remaining in the output queue to be played. - /*! - An RtAudioError (type = SYSTEM_ERROR) is thrown if an error occurs - during processing. An RtAudioError (type = INVALID_USE) is thrown if a - stream is not open. A warning is issued if the stream is already - stopped. - */ - void stopStream( void ); - - //! Stop a stream, discarding any samples remaining in the input/output queue. - /*! - An RtAudioError (type = SYSTEM_ERROR) is thrown if an error occurs - during processing. An RtAudioError (type = INVALID_USE) is thrown if a - stream is not open. A warning is issued if the stream is already - stopped. - */ - void abortStream( void ); - - //! Returns true if a stream is open and false if not. - bool isStreamOpen( void ) const throw(); - - //! Returns true if the stream is running and false if it is stopped or not open. - bool isStreamRunning( void ) const throw(); - - //! Returns the number of elapsed seconds since the stream was started. - /*! - If a stream is not open, an RtAudioError (type = INVALID_USE) will be thrown. - */ - double getStreamTime( void ); - - //! Set the stream time to a time in seconds greater than or equal to 0.0. - /*! - If a stream is not open, an RtAudioError (type = INVALID_USE) will be thrown. - */ - void setStreamTime( double time ); - - //! Returns the internal stream latency in sample frames. - /*! - The stream latency refers to delay in audio input and/or output - caused by internal buffering by the audio system and/or hardware. - For duplex streams, the returned value will represent the sum of - the input and output latencies. If a stream is not open, an - RtAudioError (type = INVALID_USE) will be thrown. If the API does not - report latency, the return value will be zero. - */ - long getStreamLatency( void ); - - //! Returns actual sample rate in use by the stream. - /*! - On some systems, the sample rate used may be slightly different - than that specified in the stream parameters. If a stream is not - open, an RtAudioError (type = INVALID_USE) will be thrown. - */ - unsigned int getStreamSampleRate( void ); - - //! Specify whether warning messages should be printed to stderr. - void showWarnings( bool value = true ) throw(); - - protected: - - void openRtApi( RtAudio::Api api ); - RtApi *rtapi_; -}; - -// Operating system dependent thread functionality. -#if defined(__WINDOWS_DS__) || defined(__WINDOWS_ASIO__) || defined(__WINDOWS_WASAPI__) - - #ifndef NOMINMAX - #define NOMINMAX - #endif - #include <windows.h> - #include <process.h> - - typedef uintptr_t ThreadHandle; - typedef CRITICAL_SECTION StreamMutex; - -#elif defined(__LINUX_ALSA__) || defined(__LINUX_PULSE__) || defined(__UNIX_JACK__) || defined(__LINUX_OSS__) || defined(__MACOSX_CORE__) - // Using pthread library for various flavors of unix. - #include <pthread.h> - - typedef pthread_t ThreadHandle; - typedef pthread_mutex_t StreamMutex; - -#else // Setup for "dummy" behavior - - #define __RTAUDIO_DUMMY__ - typedef int ThreadHandle; - typedef int StreamMutex; - -#endif - -// This global structure type is used to pass callback information -// between the private RtAudio stream structure and global callback -// handling functions. -struct CallbackInfo { - void *object; // Used as a "this" pointer. - ThreadHandle thread; - void *callback; - void *userData; - void *errorCallback; - void *apiInfo; // void pointer for API specific callback information - bool isRunning; - bool doRealtime; - int priority; - - // Default constructor. - CallbackInfo() - :object(0), callback(0), userData(0), errorCallback(0), apiInfo(0), isRunning(false), doRealtime(false) {} -}; - -// **************************************************************** // -// -// RtApi class declaration. -// -// Subclasses of RtApi contain all API- and OS-specific code necessary -// to fully implement the RtAudio API. -// -// Note that RtApi is an abstract base class and cannot be -// explicitly instantiated. The class RtAudio will create an -// instance of an RtApi subclass (RtApiOss, RtApiAlsa, -// RtApiJack, RtApiCore, RtApiDs, or RtApiAsio). -// -// **************************************************************** // - -#pragma pack(push, 1) -class S24 { - - protected: - unsigned char c3[3]; - - public: - S24() {} - - S24& operator = ( const int& i ) { - c3[0] = (i & 0x000000ff); - c3[1] = (i & 0x0000ff00) >> 8; - c3[2] = (i & 0x00ff0000) >> 16; - return *this; - } - - S24( const S24& v ) { *this = v; } - S24( const double& d ) { *this = (int) d; } - S24( const float& f ) { *this = (int) f; } - S24( const signed short& s ) { *this = (int) s; } - S24( const char& c ) { *this = (int) c; } - - int asInt() { - int i = c3[0] | (c3[1] << 8) | (c3[2] << 16); - if (i & 0x800000) i |= ~0xffffff; - return i; - } -}; -#pragma pack(pop) - -#if defined( HAVE_GETTIMEOFDAY ) - #include <sys/time.h> -#endif - -#include <sstream> - -class RtApi -{ -public: - - RtApi(); - virtual ~RtApi(); - virtual RtAudio::Api getCurrentApi( void ) = 0; - virtual unsigned int getDeviceCount( void ) = 0; - virtual RtAudio::DeviceInfo getDeviceInfo( unsigned int device ) = 0; - virtual unsigned int getDefaultInputDevice( void ); - virtual unsigned int getDefaultOutputDevice( void ); - void openStream( RtAudio::StreamParameters *outputParameters, - RtAudio::StreamParameters *inputParameters, - RtAudioFormat format, unsigned int sampleRate, - unsigned int *bufferFrames, RtAudioCallback callback, - void *userData, RtAudio::StreamOptions *options, - RtAudioErrorCallback errorCallback ); - virtual void closeStream( void ); - virtual void startStream( void ) = 0; - virtual void stopStream( void ) = 0; - virtual void abortStream( void ) = 0; - long getStreamLatency( void ); - unsigned int getStreamSampleRate( void ); - virtual double getStreamTime( void ); - virtual void setStreamTime( double time ); - bool isStreamOpen( void ) const { return stream_.state != STREAM_CLOSED; } - bool isStreamRunning( void ) const { return stream_.state == STREAM_RUNNING; } - void showWarnings( bool value ) { showWarnings_ = value; } - - -protected: - - static const unsigned int MAX_SAMPLE_RATES; - static const unsigned int SAMPLE_RATES[]; - - enum { FAILURE, SUCCESS }; - - enum StreamState { - STREAM_STOPPED, - STREAM_STOPPING, - STREAM_RUNNING, - STREAM_CLOSED = -50 - }; - - enum StreamMode { - OUTPUT, - INPUT, - DUPLEX, - UNINITIALIZED = -75 - }; - - // A protected structure used for buffer conversion. - struct ConvertInfo { - int channels; - int inJump, outJump; - RtAudioFormat inFormat, outFormat; - std::vector<int> inOffset; - std::vector<int> outOffset; - }; - - // A protected structure for audio streams. - struct RtApiStream { - unsigned int device[2]; // Playback and record, respectively. - void *apiHandle; // void pointer for API specific stream handle information - StreamMode mode; // OUTPUT, INPUT, or DUPLEX. - StreamState state; // STOPPED, RUNNING, or CLOSED - char *userBuffer[2]; // Playback and record, respectively. - char *deviceBuffer; - bool doConvertBuffer[2]; // Playback and record, respectively. - bool userInterleaved; - bool deviceInterleaved[2]; // Playback and record, respectively. - bool doByteSwap[2]; // Playback and record, respectively. - unsigned int sampleRate; - unsigned int bufferSize; - unsigned int nBuffers; - unsigned int nUserChannels[2]; // Playback and record, respectively. - unsigned int nDeviceChannels[2]; // Playback and record channels, respectively. - unsigned int channelOffset[2]; // Playback and record, respectively. - unsigned long latency[2]; // Playback and record, respectively. - RtAudioFormat userFormat; - RtAudioFormat deviceFormat[2]; // Playback and record, respectively. - StreamMutex mutex; - CallbackInfo callbackInfo; - ConvertInfo convertInfo[2]; - double streamTime; // Number of elapsed seconds since the stream started. - -#if defined(HAVE_GETTIMEOFDAY) - struct timeval lastTickTimestamp; -#endif - - RtApiStream() - :apiHandle(0), deviceBuffer(0) { device[0] = 11111; device[1] = 11111; } - }; - - typedef S24 Int24; - typedef signed short Int16; - typedef signed int Int32; - typedef float Float32; - typedef double Float64; - - std::ostringstream errorStream_; - std::string errorText_; - bool showWarnings_; - RtApiStream stream_; - bool firstErrorOccurred_; - - /*! - Protected, api-specific method that attempts to open a device - with the given parameters. This function MUST be implemented by - all subclasses. If an error is encountered during the probe, a - "warning" message is reported and FAILURE is returned. A - successful probe is indicated by a return value of SUCCESS. - */ - virtual bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, - unsigned int firstChannel, unsigned int sampleRate, - RtAudioFormat format, unsigned int *bufferSize, - RtAudio::StreamOptions *options ); - - //! A protected function used to increment the stream time. - void tickStreamTime( void ); - - //! Protected common method to clear an RtApiStream structure. - void clearStreamInfo(); - - /*! - Protected common method that throws an RtAudioError (type = - INVALID_USE) if a stream is not open. - */ - void verifyStream( void ); - - //! Protected common error method to allow global control over error handling. - void error( RtAudioError::Type type ); - - /*! - Protected method used to perform format, channel number, and/or interleaving - conversions between the user and device buffers. - */ - void convertBuffer( char *outBuffer, char *inBuffer, ConvertInfo &info ); - - //! Protected common method used to perform byte-swapping on buffers. - void byteSwapBuffer( char *buffer, unsigned int samples, RtAudioFormat format ); - - //! Protected common method that returns the number of bytes for a given format. - unsigned int formatBytes( RtAudioFormat format ); - - //! Protected common method that sets up the parameters for buffer conversion. - void setConvertInfo( StreamMode mode, unsigned int firstChannel ); -}; - -// **************************************************************** // -// -// Inline RtAudio definitions. -// -// **************************************************************** // - -inline RtAudio::Api RtAudio :: getCurrentApi( void ) throw() { return rtapi_->getCurrentApi(); } -inline unsigned int RtAudio :: getDeviceCount( void ) throw() { return rtapi_->getDeviceCount(); } -inline RtAudio::DeviceInfo RtAudio :: getDeviceInfo( unsigned int device ) { return rtapi_->getDeviceInfo( device ); } -inline unsigned int RtAudio :: getDefaultInputDevice( void ) throw() { return rtapi_->getDefaultInputDevice(); } -inline unsigned int RtAudio :: getDefaultOutputDevice( void ) throw() { return rtapi_->getDefaultOutputDevice(); } -inline void RtAudio :: closeStream( void ) throw() { return rtapi_->closeStream(); } -inline void RtAudio :: startStream( void ) { return rtapi_->startStream(); } -inline void RtAudio :: stopStream( void ) { return rtapi_->stopStream(); } -inline void RtAudio :: abortStream( void ) { return rtapi_->abortStream(); } -inline bool RtAudio :: isStreamOpen( void ) const throw() { return rtapi_->isStreamOpen(); } -inline bool RtAudio :: isStreamRunning( void ) const throw() { return rtapi_->isStreamRunning(); } -inline long RtAudio :: getStreamLatency( void ) { return rtapi_->getStreamLatency(); } -inline unsigned int RtAudio :: getStreamSampleRate( void ) { return rtapi_->getStreamSampleRate(); } -inline double RtAudio :: getStreamTime( void ) { return rtapi_->getStreamTime(); } -inline void RtAudio :: setStreamTime( double time ) { return rtapi_->setStreamTime( time ); } -inline void RtAudio :: showWarnings( bool value ) throw() { rtapi_->showWarnings( value ); } - -// RtApi Subclass prototypes. - -#if defined(__MACOSX_CORE__) - -#include <CoreAudio/AudioHardware.h> - -class RtApiCore: public RtApi -{ -public: - - RtApiCore(); - ~RtApiCore(); - RtAudio::Api getCurrentApi( void ) { return RtAudio::MACOSX_CORE; } - unsigned int getDeviceCount( void ); - RtAudio::DeviceInfo getDeviceInfo( unsigned int device ); - unsigned int getDefaultOutputDevice( void ); - unsigned int getDefaultInputDevice( void ); - void closeStream( void ); - void startStream( void ); - void stopStream( void ); - void abortStream( void ); - long getStreamLatency( void ); - - // This function is intended for internal use only. It must be - // public because it is called by the internal callback handler, - // which is not a member of RtAudio. External use of this function - // will most likely produce highly undesireable results! - bool callbackEvent( AudioDeviceID deviceId, - const AudioBufferList *inBufferList, - const AudioBufferList *outBufferList ); - - private: - - bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, - unsigned int firstChannel, unsigned int sampleRate, - RtAudioFormat format, unsigned int *bufferSize, - RtAudio::StreamOptions *options ); - static const char* getErrorCode( OSStatus code ); -}; - -#endif - -#if defined(__UNIX_JACK__) - -class RtApiJack: public RtApi -{ -public: - - RtApiJack(); - ~RtApiJack(); - RtAudio::Api getCurrentApi( void ) { return RtAudio::UNIX_JACK; } - unsigned int getDeviceCount( void ); - RtAudio::DeviceInfo getDeviceInfo( unsigned int device ); - void closeStream( void ); - void startStream( void ); - void stopStream( void ); - void abortStream( void ); - long getStreamLatency( void ); - - // This function is intended for internal use only. It must be - // public because it is called by the internal callback handler, - // which is not a member of RtAudio. External use of this function - // will most likely produce highly undesireable results! - bool callbackEvent( unsigned long nframes ); - - private: - - bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, - unsigned int firstChannel, unsigned int sampleRate, - RtAudioFormat format, unsigned int *bufferSize, - RtAudio::StreamOptions *options ); -}; - -#endif - -#if defined(__WINDOWS_ASIO__) - -class RtApiAsio: public RtApi -{ -public: - - RtApiAsio(); - ~RtApiAsio(); - RtAudio::Api getCurrentApi( void ) { return RtAudio::WINDOWS_ASIO; } - unsigned int getDeviceCount( void ); - RtAudio::DeviceInfo getDeviceInfo( unsigned int device ); - void closeStream( void ); - void startStream( void ); - void stopStream( void ); - void abortStream( void ); - long getStreamLatency( void ); - - // This function is intended for internal use only. It must be - // public because it is called by the internal callback handler, - // which is not a member of RtAudio. External use of this function - // will most likely produce highly undesireable results! - bool callbackEvent( long bufferIndex ); - - private: - - std::vector<RtAudio::DeviceInfo> devices_; - void saveDeviceInfo( void ); - bool coInitialized_; - bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, - unsigned int firstChannel, unsigned int sampleRate, - RtAudioFormat format, unsigned int *bufferSize, - RtAudio::StreamOptions *options ); -}; - -#endif - -#if defined(__WINDOWS_DS__) - -class RtApiDs: public RtApi -{ -public: - - RtApiDs(); - ~RtApiDs(); - RtAudio::Api getCurrentApi( void ) { return RtAudio::WINDOWS_DS; } - unsigned int getDeviceCount( void ); - unsigned int getDefaultOutputDevice( void ); - unsigned int getDefaultInputDevice( void ); - RtAudio::DeviceInfo getDeviceInfo( unsigned int device ); - void closeStream( void ); - void startStream( void ); - void stopStream( void ); - void abortStream( void ); - long getStreamLatency( void ); - - // This function is intended for internal use only. It must be - // public because it is called by the internal callback handler, - // which is not a member of RtAudio. External use of this function - // will most likely produce highly undesireable results! - void callbackEvent( void ); - - private: - - bool coInitialized_; - bool buffersRolling; - long duplexPrerollBytes; - std::vector<struct DsDevice> dsDevices; - bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, - unsigned int firstChannel, unsigned int sampleRate, - RtAudioFormat format, unsigned int *bufferSize, - RtAudio::StreamOptions *options ); -}; - -#endif - -#if defined(__WINDOWS_WASAPI__) - -struct IMMDeviceEnumerator; - -class RtApiWasapi : public RtApi -{ -public: - RtApiWasapi(); - ~RtApiWasapi(); - - RtAudio::Api getCurrentApi( void ) { return RtAudio::WINDOWS_WASAPI; } - unsigned int getDeviceCount( void ); - RtAudio::DeviceInfo getDeviceInfo( unsigned int device ); - unsigned int getDefaultOutputDevice( void ); - unsigned int getDefaultInputDevice( void ); - void closeStream( void ); - void startStream( void ); - void stopStream( void ); - void abortStream( void ); - -private: - bool coInitialized_; - IMMDeviceEnumerator* deviceEnumerator_; - - bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, - unsigned int firstChannel, unsigned int sampleRate, - RtAudioFormat format, unsigned int* bufferSize, - RtAudio::StreamOptions* options ); - - static DWORD WINAPI runWasapiThread( void* wasapiPtr ); - static DWORD WINAPI stopWasapiThread( void* wasapiPtr ); - static DWORD WINAPI abortWasapiThread( void* wasapiPtr ); - void wasapiThread(); -}; - -#endif - -#if defined(__LINUX_ALSA__) - -class RtApiAlsa: public RtApi -{ -public: - - RtApiAlsa(); - ~RtApiAlsa(); - RtAudio::Api getCurrentApi() { return RtAudio::LINUX_ALSA; } - unsigned int getDeviceCount( void ); - RtAudio::DeviceInfo getDeviceInfo( unsigned int device ); - void closeStream( void ); - void startStream( void ); - void stopStream( void ); - void abortStream( void ); - - // This function is intended for internal use only. It must be - // public because it is called by the internal callback handler, - // which is not a member of RtAudio. External use of this function - // will most likely produce highly undesireable results! - void callbackEvent( void ); - - private: - - std::vector<RtAudio::DeviceInfo> devices_; - void saveDeviceInfo( void ); - bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, - unsigned int firstChannel, unsigned int sampleRate, - RtAudioFormat format, unsigned int *bufferSize, - RtAudio::StreamOptions *options ); -}; - -#endif - -#if defined(__LINUX_PULSE__) - -class RtApiPulse: public RtApi -{ -public: - ~RtApiPulse(); - RtAudio::Api getCurrentApi() { return RtAudio::LINUX_PULSE; } - unsigned int getDeviceCount( void ); - RtAudio::DeviceInfo getDeviceInfo( unsigned int device ); - void closeStream( void ); - void startStream( void ); - void stopStream( void ); - void abortStream( void ); - - // This function is intended for internal use only. It must be - // public because it is called by the internal callback handler, - // which is not a member of RtAudio. External use of this function - // will most likely produce highly undesireable results! - void callbackEvent( void ); - - private: - - std::vector<RtAudio::DeviceInfo> devices_; - void saveDeviceInfo( void ); - bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, - unsigned int firstChannel, unsigned int sampleRate, - RtAudioFormat format, unsigned int *bufferSize, - RtAudio::StreamOptions *options ); -}; - -#endif - -#if defined(__LINUX_OSS__) - -class RtApiOss: public RtApi -{ -public: - - RtApiOss(); - ~RtApiOss(); - RtAudio::Api getCurrentApi() { return RtAudio::LINUX_OSS; } - unsigned int getDeviceCount( void ); - RtAudio::DeviceInfo getDeviceInfo( unsigned int device ); - void closeStream( void ); - void startStream( void ); - void stopStream( void ); - void abortStream( void ); - - // This function is intended for internal use only. It must be - // public because it is called by the internal callback handler, - // which is not a member of RtAudio. External use of this function - // will most likely produce highly undesireable results! - void callbackEvent( void ); - - private: - - bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, - unsigned int firstChannel, unsigned int sampleRate, - RtAudioFormat format, unsigned int *bufferSize, - RtAudio::StreamOptions *options ); -}; - -#endif - -#if defined(__RTAUDIO_DUMMY__) - -class RtApiDummy: public RtApi -{ -public: - - RtApiDummy() { errorText_ = "RtApiDummy: This class provides no functionality."; error( RtAudioError::WARNING ); } - RtAudio::Api getCurrentApi( void ) { return RtAudio::RTAUDIO_DUMMY; } - unsigned int getDeviceCount( void ) { return 0; } - RtAudio::DeviceInfo getDeviceInfo( unsigned int /*device*/ ) { RtAudio::DeviceInfo info; return info; } - void closeStream( void ) {} - void startStream( void ) {} - void stopStream( void ) {} - void abortStream( void ) {} - - private: - - bool probeDeviceOpen( unsigned int /*device*/, StreamMode /*mode*/, unsigned int /*channels*/, - unsigned int /*firstChannel*/, unsigned int /*sampleRate*/, - RtAudioFormat /*format*/, unsigned int * /*bufferSize*/, - RtAudio::StreamOptions * /*options*/ ) { return false; } -}; - -#endif - -#endif - -// Indentation settings for Vim and Emacs -// -// Local Variables: -// c-basic-offset: 2 -// indent-tabs-mode: nil -// End: -// -// vim: et sts=2 sw=2 - -#endif // RTAUDIO_ENABLED -GODOT- |